Merge branch 'temp8' into temp-U4-11218

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
#	src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js
#	src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/propertysettings/propertysettings.controller.js
#	src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/propertysettings/propertysettings.html
#	src/Umbraco.Web.UI.Client/src/views/content/edit.html
This commit is contained in:
Mads Rasmussen
2018-05-07 11:25:38 +02:00
657 changed files with 8222 additions and 24568 deletions

View File

@@ -15,3 +15,16 @@ indent_size = 4
# Trim trailing whitespace, limited support. # Trim trailing whitespace, limited support.
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces # https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
trim_trailing_whitespace = true trim_trailing_whitespace = true
[*.{cs,vb}]
dotnet_style_predefined_type_for_locals_parameters_members = true:error
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.severity = suggestion
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

3
.gitignore vendored
View File

@@ -121,6 +121,9 @@ src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/Umbraco/preview /src/Umbraco.Web.UI/Umbraco/preview
/src/Umbraco.Web.UI/Umbraco/preview.old /src/Umbraco.Web.UI/Umbraco/preview.old
# ignore rule for clearing out Belle (avoid rebuilding all the time)
preserve.belle
#Ignore Rule for output of generated documentation files from Grunt docserve #Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/ src/*.boltdata/

View File

@@ -43,7 +43,7 @@
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.666666)" /> <dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.666666)" />
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.666666)" /> <dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.666666)" />
<dependency id="MiniProfiler" version="[3.2.0.157,3.666666)" /> <dependency id="MiniProfiler" version="[3.2.0.157,3.666666)" />
<dependency id="MySql.Data" version="[6.10.6,6.666666)" /> <dependency id="MySql.Data" version="[6.10.7,6.666666)" />
<dependency id="Newtonsoft.Json" version="[11.0.2,11.666666)" /> <dependency id="Newtonsoft.Json" version="[11.0.2,11.666666)" />
<dependency id="NPoco" version="[3.9.3,3.666666)" /> <dependency id="NPoco" version="[3.9.3,3.666666)" />
<dependency id="NuGet.Core" version="[2.14.0,2.666666)" /> <dependency id="NuGet.Core" version="[2.14.0,2.666666)" />

View File

@@ -4,8 +4,8 @@
<configSections> <configSections>
<section name="BaseRestExtensions" xdt:Locator="Match(name)" xdt:Transform="Remove" /> <section name="BaseRestExtensions" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<section name="FileSystemProviders" xdt:Locator="Match(name)" xdt:Transform="Remove" /> <section name="FileSystemProviders" xdt:Locator="Match(name)" xdt:Transform="Remove" />
<section name="ExamineLuceneIndexSets" type="Examine.LuceneEngine.Config.IndexSets, Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" /> <section name="ExamineLuceneIndexSets" type="Umbraco.Examine.Config.IndexSets, Umbraco.Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" />
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)"> <sectionGroup name="applicationSettings" xdt:Locator="Match(name)">
<section name="umbraco.presentation.Properties.Settings" xdt:Locator="Match(name)" xdt:Transform="Remove" /> <section name="umbraco.presentation.Properties.Settings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
</sectionGroup> </sectionGroup>
@@ -67,190 +67,6 @@
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>> <profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
<sessionState customProvider="DefaultSessionProvider" xdt:Locator="Match(customProvider)" xdt:Transform="Remove"/> <sessionState customProvider="DefaultSessionProvider" xdt:Locator="Match(customProvider)" xdt:Transform="Remove"/>
<compilation xdt:Transform="InsertIfMissing" /> <compilation xdt:Transform="InsertIfMissing" />
<compilation>
<assemblies xdt:Transform="InsertIfMissing" />
<assemblies>
<add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<add assembly="System.Collections, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ComponentModel.Annotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ComponentModel.EventBasedAsync, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Contracts, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Debug, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Tools, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Diagnostics.Tracing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Globalization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq.Expressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Linq.Queryable, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.NetworkInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.Requests, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ObjectModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Emit, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Emit.ILGeneration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Emit.Lightweight, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Reflection.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Resources.ResourceManager, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.InteropServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.InteropServices.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Serialization.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Serialization.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Runtime.Serialization.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Security.Principal, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Duplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.NetTcp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.ServiceModel.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Text.Encoding, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Text.Encoding.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Text.RegularExpressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Threading, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Threading.Tasks, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Threading.Tasks.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Xml.ReaderWriter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Xml.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Xml.XmlSerializer, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
</assemblies>
</compilation>
<compilation>
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Collections" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Collections.Concurrent" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ComponentModel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ComponentModel.Annotations" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ComponentModel.EventBasedAsync" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Contracts" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Debug" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Tools" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Diagnostics.Tracing" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Dynamic.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Globalization" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.IO" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq.Expressions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Linq.Queryable" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.NetworkInformation" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Net.Requests" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ObjectModel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Emit" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Emit.ILGeneration" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Emit.Lightweight" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Reflection.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Resources.ResourceManager" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.InteropServices" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.InteropServices.WindowsRuntime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Numerics" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Serialization.Json" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Serialization.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Runtime.Serialization.Xml" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Security.Principal" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Duplex" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.NetTcp" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.ServiceModel.Security" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Text.Encoding" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Text.Encoding.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Text.RegularExpressions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Threading" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Threading.Tasks" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Threading.Tasks.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Xml.ReaderWriter" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Xml.XDocument" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
<remove assembly="System.Xml.XmlSerializer" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
</assemblies>
</compilation>
<compilation>
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Collections" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Collections.Concurrent" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ComponentModel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ComponentModel.Annotations" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ComponentModel.EventBasedAsync" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Contracts" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Debug" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Tools" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Diagnostics.Tracing" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Dynamic.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Globalization" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.IO" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq.Expressions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Linq.Queryable" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.NetworkInformation" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Requests" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ObjectModel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Emit" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Emit.ILGeneration" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Emit.Lightweight" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Reflection.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Resources.ResourceManager" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.InteropServices" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.InteropServices.WindowsRuntime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Numerics" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Serialization.Json" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Serialization.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Runtime.Serialization.Xml" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Security.Principal" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Duplex" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.NetTcp" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.ServiceModel.Security" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Text.Encoding" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Text.Encoding.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Text.RegularExpressions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Threading" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Threading.Tasks" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Threading.Tasks.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Xml.ReaderWriter" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Xml.XDocument" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Xml.XmlSerializer" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
</assemblies>
</compilation>
<xhtmlConformance xdt:Transform="Remove" /> <xhtmlConformance xdt:Transform="Remove" />

View File

@@ -86,9 +86,6 @@
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" <add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)" xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" /> xdt:Transform="SetAttributes()" />
<add initialize="true" sortOrder="5" alias="xslt" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.XsltTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" <add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco"
xdt:Locator="Match(application,alias,type)" xdt:Locator="Match(application,alias,type)"

View File

@@ -5,4 +5,6 @@
</content> </content>
<webservices xdt:Transform="Remove" /> <webservices xdt:Transform="Remove" />
<repositories xdt:Transform="Remove" />
</settings> </settings>

View File

@@ -372,8 +372,6 @@
Write-Host "Add web.config transforms to NuGet package" Write-Host "Add web.config transforms to NuGet package"
mv "$($this.BuildTemp)\WebApp\Views\Web.config" "$($this.BuildTemp)\WebApp\Views\Web.config.transform" mv "$($this.BuildTemp)\WebApp\Views\Web.config" "$($this.BuildTemp)\WebApp\Views\Web.config.transform"
# fixme - that one does not exist in .bat build either?
#mv "$($this.BuildTemp)\WebApp\Xslt\Web.config" "$($this.BuildTemp)\WebApp\Xslt\Web.config.transform"
}) })
$ubuild.DefineMethod("RestoreNuGet", $ubuild.DefineMethod("RestoreNuGet",

View File

@@ -22,9 +22,7 @@ namespace Umbraco.Core.Cache
[UmbracoWillObsolete("This cache key is only used for the legacy 'library' caching, remove in v8")] [UmbracoWillObsolete("This cache key is only used for the legacy 'library' caching, remove in v8")]
public const string MediaCacheKey = "UL_GetMedia"; public const string MediaCacheKey = "UL_GetMedia";
public const string MacroXsltCacheKey = "macroXslt_";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")] [UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string MacroCacheKey = "UmbracoMacroCache"; public const string MacroCacheKey = "UmbracoMacroCache";
@@ -39,54 +37,14 @@ namespace Umbraco.Core.Cache
[UmbracoWillObsolete("This cache key is only used for legacy template business logic caching, remove in v8")] [UmbracoWillObsolete("This cache key is only used for legacy template business logic caching, remove in v8")]
public const string TemplateFrontEndCacheKey = "template"; public const string TemplateFrontEndCacheKey = "template";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserContextCacheKey = "UmbracoUserContext";
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout"; public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserCacheKey = "UmbracoUser";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")] [UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string ContentTypeCacheKey = "UmbracoContentType"; public const string ContentTypeCacheKey = "UmbracoContentType";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")] [UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string ContentTypePropertiesCacheKey = "ContentType_PropertyTypes_Content:"; public const string ContentTypePropertiesCacheKey = "ContentType_PropertyTypes_Content:";
[Obsolete("No longer used and will be removed in v8")]
public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string LanguageCacheKey = "UmbracoLanguageCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string DomainCacheKey = "UmbracoDomainList";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string StylesheetCacheKey = "UmbracoStylesheet";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
public const string IdToKeyCacheKey = "UI2K__"; public const string IdToKeyCacheKey = "UI2K__";
public const string KeyToIdCacheKey = "UK2I__"; public const string KeyToIdCacheKey = "UK2I__";
} }

View File

@@ -24,8 +24,13 @@ namespace Umbraco.Core.Cache
protected abstract object GetEntry(string key); protected abstract object GetEntry(string key);
// read-write lock the underlying cache // read-write lock the underlying cache
protected abstract IDisposable ReadLock { get; } //protected abstract IDisposable ReadLock { get; }
protected abstract IDisposable WriteLock { get; } //protected abstract IDisposable WriteLock { get; }
protected abstract void EnterReadLock();
protected abstract void ExitReadLock();
protected abstract void EnterWriteLock();
protected abstract void ExitWriteLock();
protected string GetCacheKey(string key) protected string GetCacheKey(string key)
{ {
@@ -88,21 +93,31 @@ namespace Umbraco.Core.Cache
public virtual void ClearAllCache() public virtual void ClearAllCache()
{ {
using (WriteLock) try
{ {
EnterWriteLock();
foreach (var entry in GetDictionaryEntries() foreach (var entry in GetDictionaryEntries()
.ToArray()) .ToArray())
RemoveEntry((string) entry.Key); RemoveEntry((string) entry.Key);
} }
finally
{
ExitWriteLock();
}
} }
public virtual void ClearCacheItem(string key) public virtual void ClearCacheItem(string key)
{ {
var cacheKey = GetCacheKey(key); var cacheKey = GetCacheKey(key);
using (WriteLock) try
{ {
EnterWriteLock();
RemoveEntry(cacheKey); RemoveEntry(cacheKey);
} }
finally
{
ExitWriteLock();
}
} }
public virtual void ClearCacheObjectTypes(string typeName) public virtual void ClearCacheObjectTypes(string typeName)
@@ -110,15 +125,16 @@ namespace Umbraco.Core.Cache
var type = TypeFinder.GetTypeByName(typeName); var type = TypeFinder.GetTypeByName(typeName);
if (type == null) return; if (type == null) return;
var isInterface = type.IsInterface; var isInterface = type.IsInterface;
using (WriteLock) try
{ {
EnterWriteLock();
foreach (var entry in GetDictionaryEntries() foreach (var entry in GetDictionaryEntries()
.Where(x => .Where(x =>
{ {
// entry.Value is Lazy<object> and not null, its value may be null // entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt // remove null values as well, does not hurt
// get non-created as NonCreatedValue & exceptions as null // get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true); var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
// if T is an interface remove anything that implements that interface // if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types) // otherwise remove exact types (not inherited types)
@@ -127,14 +143,19 @@ namespace Umbraco.Core.Cache
.ToArray()) .ToArray())
RemoveEntry((string) entry.Key); RemoveEntry((string) entry.Key);
} }
finally
{
ExitWriteLock();
}
} }
public virtual void ClearCacheObjectTypes<T>() public virtual void ClearCacheObjectTypes<T>()
{ {
var typeOfT = typeof(T); var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface; var isInterface = typeOfT.IsInterface;
using (WriteLock) try
{ {
EnterWriteLock();
foreach (var entry in GetDictionaryEntries() foreach (var entry in GetDictionaryEntries()
.Where(x => .Where(x =>
{ {
@@ -142,7 +163,7 @@ namespace Umbraco.Core.Cache
// remove null values as well, does not hurt // remove null values as well, does not hurt
// compare on exact type, don't use "is" // compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null // get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true); var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
// if T is an interface remove anything that implements that interface // if T is an interface remove anything that implements that interface
// otherwise remove exact types (not inherited types) // otherwise remove exact types (not inherited types)
@@ -151,6 +172,10 @@ namespace Umbraco.Core.Cache
.ToArray()) .ToArray())
RemoveEntry((string) entry.Key); RemoveEntry((string) entry.Key);
} }
finally
{
ExitWriteLock();
}
} }
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate) public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
@@ -158,8 +183,9 @@ namespace Umbraco.Core.Cache
var typeOfT = typeof(T); var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface; var isInterface = typeOfT.IsInterface;
var plen = CacheItemPrefix.Length + 1; var plen = CacheItemPrefix.Length + 1;
using (WriteLock) try
{ {
EnterWriteLock();
foreach (var entry in GetDictionaryEntries() foreach (var entry in GetDictionaryEntries()
.Where(x => .Where(x =>
{ {
@@ -167,7 +193,7 @@ namespace Umbraco.Core.Cache
// remove null values as well, does not hurt // remove null values as well, does not hurt
// compare on exact type, don't use "is" // compare on exact type, don't use "is"
// get non-created as NonCreatedValue & exceptions as null // get non-created as NonCreatedValue & exceptions as null
var value = GetSafeLazyValue((Lazy<object>)x.Value, true); var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
if (value == null) return true; if (value == null) return true;
// if T is an interface remove anything that implements that interface // if T is an interface remove anything that implements that interface
@@ -178,30 +204,44 @@ namespace Umbraco.Core.Cache
})) }))
RemoveEntry((string) entry.Key); RemoveEntry((string) entry.Key);
} }
finally
{
ExitWriteLock();
}
} }
public virtual void ClearCacheByKeySearch(string keyStartsWith) public virtual void ClearCacheByKeySearch(string keyStartsWith)
{ {
var plen = CacheItemPrefix.Length + 1; var plen = CacheItemPrefix.Length + 1;
using (WriteLock) try
{ {
EnterWriteLock();
foreach (var entry in GetDictionaryEntries() foreach (var entry in GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith)) .Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray()) .ToArray())
RemoveEntry((string) entry.Key); RemoveEntry((string) entry.Key);
} }
finally
{
ExitWriteLock();
}
} }
public virtual void ClearCacheByKeyExpression(string regexString) public virtual void ClearCacheByKeyExpression(string regexString)
{ {
var plen = CacheItemPrefix.Length + 1; var plen = CacheItemPrefix.Length + 1;
using (WriteLock) try
{ {
EnterWriteLock();
foreach (var entry in GetDictionaryEntries() foreach (var entry in GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString)) .Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray()) .ToArray())
RemoveEntry((string) entry.Key); RemoveEntry((string) entry.Key);
} }
finally
{
ExitWriteLock();
}
} }
#endregion #endregion
@@ -212,12 +252,18 @@ namespace Umbraco.Core.Cache
{ {
var plen = CacheItemPrefix.Length + 1; var plen = CacheItemPrefix.Length + 1;
IEnumerable<DictionaryEntry> entries; IEnumerable<DictionaryEntry> entries;
using (ReadLock) try
{ {
EnterReadLock();
entries = GetDictionaryEntries() entries = GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith)) .Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked .ToArray(); // evaluate while locked
} }
finally
{
ExitReadLock();
}
return entries return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null .Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null); // backward compat, don't store null values in the cache .Where(x => x != null); // backward compat, don't store null values in the cache
@@ -228,12 +274,17 @@ namespace Umbraco.Core.Cache
const string prefix = CacheItemPrefix + "-"; const string prefix = CacheItemPrefix + "-";
var plen = prefix.Length; var plen = prefix.Length;
IEnumerable<DictionaryEntry> entries; IEnumerable<DictionaryEntry> entries;
using (ReadLock) try
{ {
EnterReadLock();
entries = GetDictionaryEntries() entries = GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString)) .Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray(); // evaluate while locked .ToArray(); // evaluate while locked
} }
finally
{
ExitReadLock();
}
return entries return entries
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null .Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null); // backward compat, don't store null values in the cache .Where(x => x != null); // backward compat, don't store null values in the cache
@@ -243,10 +294,15 @@ namespace Umbraco.Core.Cache
{ {
cacheKey = GetCacheKey(cacheKey); cacheKey = GetCacheKey(cacheKey);
Lazy<object> result; Lazy<object> result;
using (ReadLock) try
{ {
EnterReadLock();
result = GetEntry(cacheKey) as Lazy<object>; // null if key not found result = GetEntry(cacheKey) as Lazy<object>; // null if key not found
} }
finally
{
ExitReadLock();
}
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
} }

View File

@@ -79,24 +79,26 @@ namespace Umbraco.Core.Cache
#region Lock #region Lock
protected override IDisposable ReadLock private bool _entered;
protected override void EnterReadLock() => EnterWriteLock();
protected override void EnterWriteLock()
{ {
// there's no difference between ReadLock and WriteLock here if (HasContextItems)
get { return WriteLock; } {
System.Threading.Monitor.Enter(ContextItems.SyncRoot, ref _entered);
}
} }
protected override IDisposable WriteLock protected override void ExitReadLock() => ExitWriteLock();
{
// NOTE
// could think about just overriding base.Locker to return a different
// object but then we'd create a ReaderWriterLockSlim per request,
// which is less efficient than just using a basic monitor lock.
get protected override void ExitWriteLock()
{
if (_entered)
{ {
return HasContextItems _entered = false;
? (IDisposable) new MonitorLock(ContextItems.SyncRoot) System.Threading.Monitor.Exit(ContextItems.SyncRoot);
: new NoopLocker();
} }
} }
@@ -113,8 +115,9 @@ namespace Umbraco.Core.Cache
Lazy<object> result; Lazy<object> result;
using (WriteLock) try
{ {
EnterWriteLock();
result = ContextItems[cacheKey] as Lazy<object>; // null if key not found result = ContextItems[cacheKey] as Lazy<object>; // null if key not found
// cannot create value within the lock, so if result.IsValueCreated is false, just // cannot create value within the lock, so if result.IsValueCreated is false, just
@@ -127,6 +130,10 @@ namespace Umbraco.Core.Cache
ContextItems[cacheKey] = result; ContextItems[cacheKey] = result;
} }
} }
finally
{
ExitWriteLock();
}
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache // using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
// exceptions (but try again and again) and silently eat them - however at // exceptions (but try again and again) and silently eat them - however at

View File

@@ -50,14 +50,26 @@ namespace Umbraco.Core.Cache
#region Lock #region Lock
protected override IDisposable ReadLock protected override void EnterReadLock()
{ {
get { return new ReadLock(_locker); } _locker.EnterReadLock();
} }
protected override IDisposable WriteLock protected override void EnterWriteLock()
{ {
get { return new WriteLock(_locker); } _locker.EnterWriteLock();;
}
protected override void ExitReadLock()
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
protected override void ExitWriteLock()
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
} }
#endregion #endregion
@@ -118,10 +130,16 @@ namespace Umbraco.Core.Cache
// reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of // reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of
// having to re-lock in case there's no value. Would need to benchmark to figure out whether // having to re-lock in case there's no value. Would need to benchmark to figure out whether
// it's worth it, though... // it's worth it, though...
using (new ReadLock(_locker)) try
{ {
_locker.EnterReadLock();
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
} }
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
var value = result == null ? null : GetSafeLazyValue(result); var value = result == null ? null : GetSafeLazyValue(result);
if (value != null) return value; if (value != null) return value;
@@ -195,11 +213,17 @@ namespace Umbraco.Core.Cache
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value)); var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration); var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update! //NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback); _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null) public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)

View File

@@ -37,20 +37,32 @@ namespace Umbraco.Core.Cache
public virtual void ClearAllCache() public virtual void ClearAllCache()
{ {
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
MemoryCache.DisposeIfDisposable(); MemoryCache.DisposeIfDisposable();
MemoryCache = new MemoryCache("in-memory"); MemoryCache = new MemoryCache("in-memory");
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public virtual void ClearCacheItem(string key) public virtual void ClearCacheItem(string key)
{ {
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
if (MemoryCache[key] == null) return; if (MemoryCache[key] == null) return;
MemoryCache.Remove(key); MemoryCache.Remove(key);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public virtual void ClearCacheObjectTypes(string typeName) public virtual void ClearCacheObjectTypes(string typeName)
@@ -58,8 +70,9 @@ namespace Umbraco.Core.Cache
var type = TypeFinder.GetTypeByName(typeName); var type = TypeFinder.GetTypeByName(typeName);
if (type == null) return; if (type == null) return;
var isInterface = type.IsInterface; var isInterface = type.IsInterface;
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
foreach (var key in MemoryCache foreach (var key in MemoryCache
.Where(x => .Where(x =>
{ {
@@ -76,12 +89,18 @@ namespace Umbraco.Core.Cache
.ToArray()) // ToArray required to remove .ToArray()) // ToArray required to remove
MemoryCache.Remove(key); MemoryCache.Remove(key);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public virtual void ClearCacheObjectTypes<T>() public virtual void ClearCacheObjectTypes<T>()
{ {
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
var typeOfT = typeof (T); var typeOfT = typeof (T);
var isInterface = typeOfT.IsInterface; var isInterface = typeOfT.IsInterface;
foreach (var key in MemoryCache foreach (var key in MemoryCache
@@ -101,12 +120,18 @@ namespace Umbraco.Core.Cache
.ToArray()) // ToArray required to remove .ToArray()) // ToArray required to remove
MemoryCache.Remove(key); MemoryCache.Remove(key);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate) public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{ {
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
var typeOfT = typeof(T); var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface; var isInterface = typeOfT.IsInterface;
foreach (var key in MemoryCache foreach (var key in MemoryCache
@@ -127,30 +152,47 @@ namespace Umbraco.Core.Cache
.ToArray()) // ToArray required to remove .ToArray()) // ToArray required to remove
MemoryCache.Remove(key); MemoryCache.Remove(key);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public virtual void ClearCacheByKeySearch(string keyStartsWith) public virtual void ClearCacheByKeySearch(string keyStartsWith)
{ {
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
foreach (var key in MemoryCache foreach (var key in MemoryCache
.Where(x => x.Key.InvariantStartsWith(keyStartsWith)) .Where(x => x.Key.InvariantStartsWith(keyStartsWith))
.Select(x => x.Key) .Select(x => x.Key)
.ToArray()) // ToArray required to remove .ToArray()) // ToArray required to remove
MemoryCache.Remove(key); MemoryCache.Remove(key);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
public virtual void ClearCacheByKeyExpression(string regexString) public virtual void ClearCacheByKeyExpression(string regexString)
{ {
using (new WriteLock(_locker)) try
{ {
_locker.EnterWriteLock();
foreach (var key in MemoryCache foreach (var key in MemoryCache
.Where(x => Regex.IsMatch(x.Key, regexString)) .Where(x => Regex.IsMatch(x.Key, regexString))
.Select(x => x.Key) .Select(x => x.Key)
.ToArray()) // ToArray required to remove .ToArray()) // ToArray required to remove
MemoryCache.Remove(key); MemoryCache.Remove(key);
} }
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
} }
#endregion #endregion
@@ -160,12 +202,18 @@ namespace Umbraco.Core.Cache
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith) public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{ {
KeyValuePair<string, object>[] entries; KeyValuePair<string, object>[] entries;
using (new ReadLock(_locker)) try
{ {
_locker.EnterReadLock();
entries = MemoryCache entries = MemoryCache
.Where(x => x.Key.InvariantStartsWith(keyStartsWith)) .Where(x => x.Key.InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked .ToArray(); // evaluate while locked
} }
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
return entries return entries
.Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null .Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null) // backward compat, don't store null values in the cache .Where(x => x != null) // backward compat, don't store null values in the cache
@@ -175,12 +223,18 @@ namespace Umbraco.Core.Cache
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString) public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{ {
KeyValuePair<string, object>[] entries; KeyValuePair<string, object>[] entries;
using (new ReadLock(_locker)) try
{ {
_locker.EnterReadLock();
entries = MemoryCache entries = MemoryCache
.Where(x => Regex.IsMatch(x.Key, regexString)) .Where(x => Regex.IsMatch(x.Key, regexString))
.ToArray(); // evaluate while locked .ToArray(); // evaluate while locked
} }
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
return entries return entries
.Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null .Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
.Where(x => x != null) // backward compat, don't store null values in the cache .Where(x => x != null) // backward compat, don't store null values in the cache
@@ -190,10 +244,16 @@ namespace Umbraco.Core.Cache
public object GetCacheItem(string cacheKey) public object GetCacheItem(string cacheKey)
{ {
Lazy<object> result; Lazy<object> result;
using (new ReadLock(_locker)) try
{ {
_locker.EnterReadLock();
result = MemoryCache.Get(cacheKey) as Lazy<object>; // null if key not found result = MemoryCache.Get(cacheKey) as Lazy<object>; // null if key not found
} }
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null
} }

View File

@@ -0,0 +1,41 @@
using System;
namespace Umbraco.Core.Collections
{
/// <summary>
/// Represents a composite key of (string, string) for fast dictionaries.
/// </summary>
/// <remarks>
/// <para>The string parts of the key are case-insensitive.</para>
/// <para>Null is a valid value for both parts.</para>
/// </remarks>
public struct CompositeStringStringKey : IEquatable<CompositeStringStringKey>
{
private readonly string _key1;
private readonly string _key2;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeStringStringKey"/> struct.
/// </summary>
public CompositeStringStringKey(string key1, string key2)
{
_key1 = key1?.ToLowerInvariant() ?? "NULL";
_key2 = key2?.ToLowerInvariant() ?? "NULL";
}
public bool Equals(CompositeStringStringKey other)
=> _key2 == other._key2 && _key1 == other._key1;
public override bool Equals(object obj)
=> obj is CompositeStringStringKey other && _key2 == other._key2 && _key1 == other._key1;
public override int GetHashCode()
=> _key2.GetHashCode() * 31 + _key1.GetHashCode();
public static bool operator ==(CompositeStringStringKey key1, CompositeStringStringKey key2)
=> key1._key2 == key2._key2 && key1._key1 == key2._key1;
public static bool operator !=(CompositeStringStringKey key1, CompositeStringStringKey key2)
=> key1._key2 != key2._key2 || key1._key1 != key2._key1;
}
}

View File

@@ -50,10 +50,16 @@ namespace Umbraco.Core.Collections
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception> /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(T item) public bool Remove(T item)
{ {
using (new WriteLock(_instanceLocker)) try
{ {
_instanceLocker.EnterWriteLock();
return _innerSet.Remove(item); return _innerSet.Remove(item);
} }
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
} }
@@ -86,10 +92,16 @@ namespace Umbraco.Core.Collections
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception> /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public void Add(T item) public void Add(T item)
{ {
using (new WriteLock(_instanceLocker)) try
{ {
_instanceLocker.EnterWriteLock();
_innerSet.Add(item); _innerSet.Add(item);
} }
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
} }
/// <summary> /// <summary>
@@ -101,13 +113,20 @@ namespace Umbraco.Core.Collections
{ {
var clone = GetThreadSafeClone(); var clone = GetThreadSafeClone();
if (clone.Contains(item)) return false; if (clone.Contains(item)) return false;
using (new WriteLock(_instanceLocker)) try
{ {
_instanceLocker.EnterWriteLock();
//double check //double check
if (_innerSet.Contains(item)) return false; if (_innerSet.Contains(item)) return false;
_innerSet.Add(item); _innerSet.Add(item);
return true; return true;
} }
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
} }
/// <summary> /// <summary>
@@ -116,10 +135,16 @@ namespace Umbraco.Core.Collections
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception> /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
public void Clear() public void Clear()
{ {
using (new WriteLock(_instanceLocker)) try
{ {
_instanceLocker.EnterWriteLock();
_innerSet.Clear(); _innerSet.Clear();
} }
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
} }
/// <summary> /// <summary>
@@ -147,10 +172,16 @@ namespace Umbraco.Core.Collections
private HashSet<T> GetThreadSafeClone() private HashSet<T> GetThreadSafeClone()
{ {
HashSet<T> clone = null; HashSet<T> clone = null;
using (new WriteLock(_instanceLocker)) try
{ {
_instanceLocker.EnterWriteLock();
clone = new HashSet<T>(_innerSet, _innerSet.Comparer); clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
} }
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
return clone; return clone;
} }

View File

@@ -76,7 +76,6 @@ namespace Umbraco.Core.Composing.CompositionRoots
container.RegisterSingleton<IPartialViewRepository, PartialViewRepository>(); container.RegisterSingleton<IPartialViewRepository, PartialViewRepository>();
container.RegisterSingleton<IScriptRepository, ScriptRepository>(); container.RegisterSingleton<IScriptRepository, ScriptRepository>();
container.RegisterSingleton<IStylesheetRepository, StylesheetRepository>(); container.RegisterSingleton<IStylesheetRepository, StylesheetRepository>();
container.RegisterSingleton<IXsltFileRepository, XsltFileRepository>();
} }
} }
} }

View File

@@ -311,15 +311,15 @@ namespace Umbraco.Core.Composing
// we HAVE to let LightInject throw - and catch at THE OUTERMOST if InvalidOperationException in LightInject.Anything! // we HAVE to let LightInject throw - and catch at THE OUTERMOST if InvalidOperationException in LightInject.Anything!
return factory.GetInstance(tService, serviceName, args); return factory.GetInstance(tService, serviceName, args);
try //try
{ //{
return factory.GetInstance(tService, serviceName, args); // return factory.GetInstance(tService, serviceName, args);
} //}
catch (Exception e) //catch (Exception e)
{ //{
LightInjectException.TryThrow(e, implementingType); // LightInjectException.TryThrow(e, implementingType);
throw; // throw;
} //}
} }
/// <summary> /// <summary>

View File

@@ -1,47 +0,0 @@
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class DeveloperElement : ConfigurationElement, IDeveloperSection
{
private AppCodeFileExtensionsElement _default;
[ConfigurationProperty("appCodeFileExtensions")]
internal AppCodeFileExtensionsElement AppCodeFileExtensions
{
get
{
if (_default != null)
{
return _default;
}
//here we need to check if this element is defined, if it is not then we'll setup the defaults
var prop = Properties["appCodeFileExtensions"];
var autoFill = this[prop] as ConfigurationElement;
if (autoFill != null && autoFill.ElementInformation.IsPresent == false)
{
var collection = new AppCodeFileExtensionsCollection
{
new FileExtensionElement {RawValue = "cs"},
new FileExtensionElement {RawValue = "vb"}
};
_default = new AppCodeFileExtensionsElement
{
AppCodeFileExtensionsCollection = collection
};
return _default;
}
return (AppCodeFileExtensionsElement)base["appCodeFileExtensions"];
}
}
IEnumerable<IFileExtension> IDeveloperSection.AppCodeFileExtensions
{
get { return AppCodeFileExtensions.AppCodeFileExtensionsCollection; }
}
}
}

View File

@@ -1,48 +0,0 @@
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class DistributedCallElement : ConfigurationElement, IDistributedCallSection
{
[ConfigurationProperty("enable", DefaultValue = false)]
internal bool Enabled
{
get { return (bool)base["enable"]; }
}
[ConfigurationProperty("user")]
internal InnerTextConfigurationElement<int> UserId
{
get
{
return new OptionalInnerTextConfigurationElement<int>(
(InnerTextConfigurationElement<int>)this["user"],
//set the default
0);
}
}
[ConfigurationCollection(typeof(ServerCollection), AddItemName = "server")]
[ConfigurationProperty("servers", IsDefaultCollection = true)]
internal ServerCollection Servers
{
get { return (ServerCollection)base["servers"]; }
}
bool IDistributedCallSection.Enabled
{
get { return Enabled; }
}
int IDistributedCallSection.UserId
{
get { return UserId; }
}
IEnumerable<IServer> IDistributedCallSection.Servers
{
get { return Servers; }
}
}
}

View File

@@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IDeveloperSection : IUmbracoConfigurationSection
{
IEnumerable<IFileExtension> AppCodeFileExtensions { get; }
}
}

View File

@@ -1,13 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IDistributedCallSection : IUmbracoConfigurationSection
{
bool Enabled { get; }
int UserId { get; }
IEnumerable<IServer> Servers { get; }
}
}

View File

@@ -1,20 +0,0 @@
using System;
using System.ComponentModel;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("This is no longer used and will be removed in future versions")]
public interface ILink
{
string Application { get; }
string ApplicationUrl { get; }
string Language { get; }
string UserType { get; }
string HelpUrl { get; }
}
}

View File

@@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IRepositoriesSection : IUmbracoConfigurationSection
{
IEnumerable<IRepository> Repositories { get; }
}
}

View File

@@ -1,14 +0,0 @@
using System;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IRepository
{
string Name { get; }
Guid Id { get; }
string RepositoryUrl { get; }
string WebServiceUrl { get; }
bool HasCustomWebServiceUrl { get; }
string RestApiUrl { get; }
}
}

View File

@@ -1,12 +0,0 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IServer
{
string ForcePortnumber { get; }
string ForceProtocol { get; }
string ServerAddress { get; }
string AppId { get; }
string ServerName { get; }
}
}

View File

@@ -4,13 +4,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{ {
public interface ITemplatesSection : IUmbracoConfigurationSection public interface ITemplatesSection : IUmbracoConfigurationSection
{ {
bool UseAspNetMasterPages { get; }
bool EnableSkinSupport { get; }
RenderingEngine DefaultRenderingEngine { get; } RenderingEngine DefaultRenderingEngine { get; }
[Obsolete("This has no affect and will be removed in future versions")]
bool EnableTemplateFolders { get; }
} }
} }

View File

@@ -14,18 +14,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IRequestHandlerSection RequestHandler { get; } IRequestHandlerSection RequestHandler { get; }
ITemplatesSection Templates { get; } ITemplatesSection Templates { get; }
IDeveloperSection Developer { get; }
ILoggingSection Logging { get; } ILoggingSection Logging { get; }
IScheduledTasksSection ScheduledTasks { get; } IScheduledTasksSection ScheduledTasks { get; }
IDistributedCallSection DistributedCall { get; }
IRepositoriesSection PackageRepositories { get; }
IProvidersSection Providers { get; } IProvidersSection Providers { get; }
IWebRoutingSection WebRouting { get; } IWebRoutingSection WebRouting { get; }

View File

@@ -1,36 +0,0 @@
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class RepositoriesCollection : ConfigurationElementCollection, IEnumerable<IRepository>
{
internal void Add(RepositoryElement item)
{
BaseAdd(item);
}
protected override ConfigurationElement CreateNewElement()
{
return new RepositoryElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((RepositoryElement)element).Id;
}
IEnumerator<IRepository> IEnumerable<IRepository>.GetEnumerator()
{
for (var i = 0; i < Count; i++)
{
yield return BaseGet(i) as IRepository;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class RepositoriesElement : ConfigurationElement, IRepositoriesSection
{
[ConfigurationCollection(typeof(RepositoriesCollection), AddItemName = "repository")]
[ConfigurationProperty("", IsDefaultCollection = true)]
internal RepositoriesCollection Repositories
{
get { return (RepositoriesCollection) base[""]; }
set { base[""] = value; }
}
IEnumerable<IRepository> IRepositoriesSection.Repositories
{
get { return Repositories; }
}
}
}

View File

@@ -1,19 +0,0 @@
using System;
using System.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public static class RepositoryConfigExtensions
{
//Our package repo
private static readonly Guid RepoGuid = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66");
public static IRepository GetDefault(this IRepositoriesSection repos)
{
var found = repos.Repositories.FirstOrDefault(x => x.Id == RepoGuid);
if (found == null)
throw new InvalidOperationException("No default package repository found with id " + RepoGuid);
return found;
}
}
}

View File

@@ -1,53 +0,0 @@
using System;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class RepositoryElement : ConfigurationElement, IRepository
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
[ConfigurationProperty("guid", IsRequired = true)]
public Guid Id
{
get { return (Guid)base["guid"]; }
set { base["guid"] = value; }
}
[ConfigurationProperty("repositoryurl", DefaultValue = "http://packages.umbraco.org")]
public string RepositoryUrl
{
get { return (string)base["repositoryurl"]; }
set { base["repositoryurl"] = value; }
}
[ConfigurationProperty("webserviceurl", DefaultValue = "/umbraco/webservices/api/repository.asmx")]
public string WebServiceUrl
{
get { return (string)base["webserviceurl"]; }
set { base["webserviceurl"] = value; }
}
public bool HasCustomWebServiceUrl
{
get
{
var prop = Properties["webserviceurl"];
return (string) prop.DefaultValue != (string) this[prop];
}
}
[ConfigurationProperty("restapiurl", DefaultValue = "https://our.umbraco.org/webapi/packages/v1")]
public string RestApiUrl
{
get { return (string)base["restapiurl"]; }
set { base["restapiurl"] = value; }
}
}
}

View File

@@ -41,7 +41,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("authCookieName")] [ConfigurationProperty("authCookieName")]
internal InnerTextConfigurationElement<string> AuthCookieName internal InnerTextConfigurationElement<string> AuthCookieName
{ {
get { return GetOptionalTextElement("authCookieName", Constants.Web.AuthCookieName); } get { return GetOptionalTextElement("authCookieName", "UMB_UCONTEXT"); }
} }
[ConfigurationProperty("authCookieDomain")] [ConfigurationProperty("authCookieDomain")]

View File

@@ -1,31 +0,0 @@
using System.Collections.Generic;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ServerCollection : ConfigurationElementCollection, IEnumerable<IServer>
{
protected override ConfigurationElement CreateNewElement()
{
return new ServerElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ServerElement)element).Value;
}
IEnumerator<IServer> IEnumerable<IServer>.GetEnumerator()
{
for (var i = 0; i < Count; i++)
{
yield return BaseGet(i) as IServer;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -1,49 +0,0 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ServerElement : InnerTextConfigurationElement<string>, IServer
{
public string ForcePortnumber
{
get
{
return RawXml.Attribute("forcePortnumber") == null
? null
: RawXml.Attribute("forcePortnumber").Value;
}
}
public string ForceProtocol
{
get
{
return RawXml.Attribute("forceProtocol") == null
? null
: RawXml.Attribute("forceProtocol").Value;
}
}
string IServer.ServerAddress
{
get { return Value; }
}
public string AppId
{
get
{
return RawXml.Attribute("appId") == null
? null
: RawXml.Attribute("appId").Value;
}
}
public string ServerName
{
get
{
return RawXml.Attribute("serverName") == null
? null
: RawXml.Attribute("serverName").Value;
}
}
}
}

View File

@@ -5,50 +5,16 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{ {
internal class TemplatesElement : UmbracoConfigurationElement, ITemplatesSection internal class TemplatesElement : UmbracoConfigurationElement, ITemplatesSection
{ {
[ConfigurationProperty("useAspNetMasterPages")]
internal InnerTextConfigurationElement<bool> UseAspNetMasterPages
{
get { return GetOptionalTextElement("useAspNetMasterPages", true); }
}
[ConfigurationProperty("enableSkinSupport")]
internal InnerTextConfigurationElement<bool> EnableSkinSupport
{
get { return GetOptionalTextElement("enableSkinSupport", true); }
}
[ConfigurationProperty("defaultRenderingEngine", IsRequired = true)] [ConfigurationProperty("defaultRenderingEngine", IsRequired = true)]
internal InnerTextConfigurationElement<RenderingEngine> DefaultRenderingEngine internal InnerTextConfigurationElement<RenderingEngine> DefaultRenderingEngine
{ {
get { return GetOptionalTextElement("defaultRenderingEngine", RenderingEngine.Mvc); } get { return GetOptionalTextElement("defaultRenderingEngine", RenderingEngine.Mvc); }
} }
[Obsolete("This has no affect and will be removed in future versions")]
[ConfigurationProperty("enableTemplateFolders")]
internal InnerTextConfigurationElement<bool> EnableTemplateFolders
{
get { return GetOptionalTextElement("enableTemplateFolders", false); }
}
bool ITemplatesSection.UseAspNetMasterPages
{
get { return UseAspNetMasterPages; }
}
bool ITemplatesSection.EnableSkinSupport
{
get { return EnableSkinSupport; }
}
RenderingEngine ITemplatesSection.DefaultRenderingEngine RenderingEngine ITemplatesSection.DefaultRenderingEngine
{ {
get { return DefaultRenderingEngine; } get { return DefaultRenderingEngine; }
} }
[Obsolete("This has no affect and will be removed in future versions")]
bool ITemplatesSection.EnableTemplateFolders
{
get { return EnableTemplateFolders; }
}
} }
} }

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
internal BackOfficeElement BackOffice internal BackOfficeElement BackOffice
{ {
get { return (BackOfficeElement)this["backOffice"]; } get { return (BackOfficeElement)this["backOffice"]; }
} }
[ConfigurationProperty("content")] [ConfigurationProperty("content")]
internal ContentElement Content internal ContentElement Content
@@ -37,14 +37,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{ {
get { return (TemplatesElement)this["templates"]; } get { return (TemplatesElement)this["templates"]; }
} }
[ConfigurationProperty("developer")]
internal DeveloperElement Developer
{
get { return (DeveloperElement)this["developer"]; }
}
[ConfigurationProperty("logging")] [ConfigurationProperty("logging")]
internal LoggingElement Logging internal LoggingElement Logging
{ {
@@ -57,55 +50,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return (ScheduledTasksElement)this["scheduledTasks"]; } get { return (ScheduledTasksElement)this["scheduledTasks"]; }
} }
[ConfigurationProperty("distributedCall")]
internal DistributedCallElement DistributedCall
{
get { return (DistributedCallElement)this["distributedCall"]; }
}
private RepositoriesElement _defaultRepositories;
[ConfigurationProperty("repositories")]
internal RepositoriesElement PackageRepositories
{
get
{
if (_defaultRepositories != null)
{
return _defaultRepositories;
}
//here we need to check if this element is defined, if it is not then we'll setup the defaults
var prop = Properties["repositories"];
var repos = this[prop] as ConfigurationElement;
if (repos != null && repos.ElementInformation.IsPresent == false)
{
var collection = new RepositoriesCollection
{
new RepositoryElement() {Name = "Umbraco package Repository", Id = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66")}
};
_defaultRepositories = new RepositoriesElement()
{
Repositories = collection
};
return _defaultRepositories;
}
//now we need to ensure there is *always* our umbraco repo! its hard coded in the codebase!
var reposElement = (RepositoriesElement)base["repositories"];
if (reposElement.Repositories.All(x => x.Id != new Guid("65194810-1f85-11dd-bd0b-0800200c9a66")))
{
reposElement.Repositories.Add(new RepositoryElement() { Name = "Umbraco package Repository", Id = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66") });
}
return reposElement;
}
}
[ConfigurationProperty("providers")] [ConfigurationProperty("providers")]
internal ProvidersElement Providers internal ProvidersElement Providers
{ {
@@ -141,11 +85,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IBackOfficeSection IUmbracoSettingsSection.BackOffice IBackOfficeSection IUmbracoSettingsSection.BackOffice
{ {
get { return BackOffice; } get { return BackOffice; }
}
IDeveloperSection IUmbracoSettingsSection.Developer
{
get { return Developer; }
} }
ILoggingSection IUmbracoSettingsSection.Logging ILoggingSection IUmbracoSettingsSection.Logging
@@ -157,17 +96,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{ {
get { return ScheduledTasks; } get { return ScheduledTasks; }
} }
IDistributedCallSection IUmbracoSettingsSection.DistributedCall
{
get { return DistributedCall; }
}
IRepositoriesSection IUmbracoSettingsSection.PackageRepositories
{
get { return PackageRepositories; }
}
IProvidersSection IUmbracoSettingsSection.Providers IProvidersSection IUmbracoSettingsSection.Providers
{ {
get { return Providers; } get { return Providers; }

View File

@@ -121,9 +121,7 @@
public const string Templates = "templates"; public const string Templates = "templates";
public const string RelationTypes = "relationTypes"; public const string RelationTypes = "relationTypes";
public const string Xslt = "xslt";
public const string Languages = "languages"; public const string Languages = "languages";
/// <summary> /// <summary>

View File

@@ -21,7 +21,6 @@
public const string StylesheetFileSystem = "StylesheetFileSystem"; public const string StylesheetFileSystem = "StylesheetFileSystem";
public const string MasterpageFileSystem = "MasterpageFileSystem"; public const string MasterpageFileSystem = "MasterpageFileSystem";
public const string ViewFileSystem = "ViewFileSystem"; public const string ViewFileSystem = "ViewFileSystem";
public const string XsltFileSystem = "XsltFileSystem";
public const string JavascriptLibraryFileSystem = "JavascriptLibraryFileSystem"; public const string JavascriptLibraryFileSystem = "JavascriptLibraryFileSystem";
} }
} }

View File

@@ -0,0 +1,15 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the constants used for the Umbraco package repository
/// </summary>
public static class PackageRepository
{
public const string RestApiBaseUrl = "https://our.umbraco.org/webapi/packages/v1";
public const string DefaultRepositoryName = "Umbraco package Repository";
public const string DefaultRepositoryId = "65194810-1f85-11dd-bd0b-0800200c9a66";
}
}
}

View File

@@ -23,13 +23,6 @@ namespace Umbraco.Core
public const string InstallerCookieName = "umb_installId"; public const string InstallerCookieName = "umb_installId";
/// <summary>
/// The auth cookie name
/// </summary>
[Obsolete("DO NOT USE THIS, USE ISecuritySection.AuthCookieName, this will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string AuthCookieName = "UMB_UCONTEXT";
} }
} }
} }

View File

@@ -0,0 +1,22 @@
using Umbraco.Core.Models;
namespace Umbraco.Core
{
/// <summary>
/// Provides extension methods for various enumerations.
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// Determines whether a variation has all flags set.
/// </summary>
public static bool Has(this ContentVariation variation, ContentVariation values)
=> (variation & values) == values;
/// <summary>
/// Determines whether a variation has at least a flag set.
/// </summary>
public static bool HasAny(this ContentVariation variation, ContentVariation values)
=> (variation & values) != ContentVariation.Unknown;
}
}

View File

@@ -92,21 +92,6 @@ namespace Umbraco.Core
} }
} }
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
public static IEnumerable<TItem> ForEach<TItem>(this IEnumerable<TItem> items, Action<TItem> action)
{
if (items != null)
{
foreach (TItem item in items)
{
action(item);
}
}
return items;
}
/// <summary>The flatten list.</summary> /// <summary>The flatten list.</summary>
/// <param name="e">The items.</param> /// <param name="e">The items.</param>
/// <param name="f">The select child.</param> /// <param name="f">The select child.</param>

View File

@@ -19,7 +19,7 @@ namespace Umbraco.Core.Events
/// <summary> /// <summary>
/// Filename, file path, fully qualified class name, or other key used by the macro engine to do it's processing of the faulting macro. /// Filename, file path, fully qualified class name, or other key used by the macro engine to do it's processing of the faulting macro.
/// </summary> /// </summary>
public string ItemKey { get; set; } public string MacroSource { get; set; }
/// <summary> /// <summary>
/// Exception raised. /// Exception raised.

View File

@@ -26,10 +26,8 @@ namespace Umbraco.Core.IO
private ShadowWrapper _partialViewsFileSystem; private ShadowWrapper _partialViewsFileSystem;
private ShadowWrapper _stylesheetsFileSystem; private ShadowWrapper _stylesheetsFileSystem;
private ShadowWrapper _scriptsFileSystem; private ShadowWrapper _scriptsFileSystem;
private ShadowWrapper _xsltFileSystem;
private ShadowWrapper _masterPagesFileSystem; private ShadowWrapper _masterPagesFileSystem;
private ShadowWrapper _mvcViewsFileSystem; private ShadowWrapper _mvcViewsFileSystem;
private ShadowWrapper _javaScriptLibraryFileSystem;
// well-known file systems lazy initialization // well-known file systems lazy initialization
private object _wkfsLock = new object(); private object _wkfsLock = new object();
@@ -103,16 +101,7 @@ namespace Umbraco.Core.IO
return _scriptsFileSystem; return _scriptsFileSystem;
} }
} }
public IFileSystem XsltFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _xsltFileSystem;
}
}
public IFileSystem MasterPagesFileSystem public IFileSystem MasterPagesFileSystem
{ {
get get
@@ -163,7 +152,6 @@ namespace Umbraco.Core.IO
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews); var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css); var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts); var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages); var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews); var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
var javaScriptLibraryFileSystem = new PhysicalFileSystem(SystemDirectories.JavaScriptLibrary); var javaScriptLibraryFileSystem = new PhysicalFileSystem(SystemDirectories.JavaScriptLibrary);
@@ -172,7 +160,6 @@ namespace Umbraco.Core.IO
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", () => IsScoped()); _partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", () => IsScoped());
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", () => IsScoped()); _stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", () => IsScoped());
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", () => IsScoped()); _scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", () => IsScoped());
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", () => IsScoped());
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", () => IsScoped()); _masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", () => IsScoped());
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped()); _mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped());
_javascriptLibraryFileSystem = new ShadowWrapper(javaScriptLibraryFileSystem, "Lib", () => IsScoped()); _javascriptLibraryFileSystem = new ShadowWrapper(javaScriptLibraryFileSystem, "Lib", () => IsScoped());
@@ -366,14 +353,13 @@ namespace Umbraco.Core.IO
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems(); if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
var typed = _wrappers.ToArray(); var typed = _wrappers.ToArray();
var wrappers = new ShadowWrapper[typed.Length + 7]; var wrappers = new ShadowWrapper[typed.Length + 6];
var i = 0; var i = 0;
while (i < typed.Length) wrappers[i] = typed[i++]; while (i < typed.Length) wrappers[i] = typed[i++];
wrappers[i++] = _macroPartialFileSystem; wrappers[i++] = _macroPartialFileSystem;
wrappers[i++] = _partialViewsFileSystem; wrappers[i++] = _partialViewsFileSystem;
wrappers[i++] = _stylesheetsFileSystem; wrappers[i++] = _stylesheetsFileSystem;
wrappers[i++] = _scriptsFileSystem; wrappers[i++] = _scriptsFileSystem;
wrappers[i++] = _xsltFileSystem;
wrappers[i++] = _masterPagesFileSystem; wrappers[i++] = _masterPagesFileSystem;
wrappers[i] = _mvcViewsFileSystem; wrappers[i] = _mvcViewsFileSystem;

View File

@@ -27,13 +27,7 @@ namespace Umbraco.Core.IO
{ {
return _masterPageFileSystem.FileExists(GetFilePath(t)); return _masterPageFileSystem.FileExists(GetFilePath(t));
} }
[Obsolete("This is only used for legacy purposes and will be removed in future versions")]
internal string GetPhysicalFilePath(ITemplate t)
{
return _masterPageFileSystem.GetFullPath(GetFilePath(t.Alias));
}
private string GetFilePath(ITemplate t) private string GetFilePath(ITemplate t)
{ {
return GetFilePath(t.Alias); return GetFilePath(t.Alias);

View File

@@ -335,35 +335,35 @@ namespace Umbraco.Core.IO
// fixme - what's below belongs to the upload property editor, not the media filesystem! // fixme - what's below belongs to the upload property editor, not the media filesystem!
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream, int? languageId = null, string segment = null) public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
{ {
var property = GetProperty(content, propertyTypeAlias); var property = GetProperty(content, propertyTypeAlias);
var oldpath = property.GetValue(languageId, segment) is string svalue ? GetRelativePath(svalue) : null; var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath); var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
property.SetValue(GetUrl(filepath), languageId, segment); property.SetValue(GetUrl(filepath), culture, segment);
SetUploadFile(content, property, filepath, filestream, languageId, segment); SetUploadFile(content, property, filepath, filestream, culture, segment);
} }
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath, int? languageId = null, string segment = null) public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath, string culture = null, string segment = null)
{ {
var property = GetProperty(content, propertyTypeAlias); var property = GetProperty(content, propertyTypeAlias);
// fixme delete? // fixme delete?
var oldpath = property.GetValue(languageId, segment) is string svalue ? GetRelativePath(svalue) : null; var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath) if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
DeleteFile(oldpath); DeleteFile(oldpath);
property.SetValue(GetUrl(filepath), languageId, segment); property.SetValue(GetUrl(filepath), culture, segment);
using (var filestream = OpenFile(filepath)) using (var filestream = OpenFile(filepath))
{ {
SetUploadFile(content, property, filepath, filestream, languageId, segment); SetUploadFile(content, property, filepath, filestream, culture, segment);
} }
} }
// sets a file for the FileUpload property editor // sets a file for the FileUpload property editor
// ie generates thumbnails and populates autofill properties // ie generates thumbnails and populates autofill properties
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream, int? languageId = null, string segment = null) private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream, string culture = null, string segment = null)
{ {
// will use filepath for extension, and filestream for length // will use filepath for extension, and filestream for length
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, languageId, segment); UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, culture, segment);
} }
#endregion #endregion

View File

@@ -46,8 +46,6 @@ namespace Umbraco.Core.IO
public static string WebServices => IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices"); public static string WebServices => IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices");
public static string Xslt => IOHelper.ReturnPath("umbracoXsltPath", "~/xslt");
//by default the packages folder should exist in the data folder //by default the packages folder should exist in the data folder
public static string Packages => IOHelper.ReturnPath("umbracoPackagesPath", Data + IOHelper.DirSepChar + "packages"); public static string Packages => IOHelper.ReturnPath("umbracoPackagesPath", Data + IOHelper.DirSepChar + "packages");

View File

@@ -67,10 +67,9 @@ namespace Umbraco.Core.IO
modelNamespaceAlias = "ContentModels"; modelNamespaceAlias = "ContentModels";
// either // either
// @inherits Umbraco.Web.Mvc.UmbracoTemplatePage // @inherits Umbraco.Web.Mvc.UmbracoViewPage
// @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ModelClass> // @inherits Umbraco.Web.Mvc.UmbracoViewPage<ModelClass>
// @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ContentModels.ModelClass> content.Append("@inherits Umbraco.Web.Mvc.UmbracoViewPage");
content.Append("@inherits Umbraco.Web.Mvc.UmbracoTemplatePage");
if (modelClassName.IsNullOrWhiteSpace() == false) if (modelClassName.IsNullOrWhiteSpace() == false)
{ {
content.Append("<"); content.Append("<");

View File

@@ -1,21 +0,0 @@
// fixme - remove this file
//using log4net.Core;
//using log4net.Util;
//using System;
//using System.Collections.Concurrent;
//using System.Threading;
//using System.Threading.Tasks;
//namespace Umbraco.Core.Logging
//{
// /// <summary>
// /// An asynchronous appender based on <see cref="BlockingCollection{T}"/>
// /// </summary>
// /// <remarks>
// /// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
// /// </remarks>
// [Obsolete("Use the Log4Net.Async.ParallelForwardingAppender instead this will be removed in future versions")]
// public class ParallelForwardingAppender : Log4Net.Async.ParallelForwardingAppender
// {
// }
//}

View File

@@ -179,7 +179,7 @@ namespace Umbraco.Core.Macros
// Check whether it's a single tag (<?.../>) or a tag with children (<?..>...</?...>) // Check whether it's a single tag (<?.../>) or a tag with children (<?..>...</?...>)
if (tag.Substring(tag.Length - 2, 1) != "/" && tag.IndexOf(" ") > -1) if (tag.Substring(tag.Length - 2, 1) != "/" && tag.IndexOf(" ") > -1)
{ {
String closingTag = "</" + (tag.Substring(1, tag.IndexOf(" ") - 1)) + ">"; string closingTag = "</" + (tag.Substring(1, tag.IndexOf(" ") - 1)) + ">";
// Tag with children are only used when a macro is inserted by the umbraco-editor, in the // Tag with children are only used when a macro is inserted by the umbraco-editor, in the
// following format: "<?UMBRACO_MACRO ...><IMG SRC="..."..></?UMBRACO_MACRO>", so we // following format: "<?UMBRACO_MACRO ...><IMG SRC="..."..></?UMBRACO_MACRO>", so we
// need to delete extra information inserted which is the image-tag and the closing // need to delete extra information inserted which is the image-tag and the closing

View File

@@ -1,17 +0,0 @@
namespace Umbraco.Core.Macros
{
/// <summary>
/// Encapsulates what an xslt extension object is when used for macros
/// </summary>
internal sealed class XsltExtension
{
public XsltExtension(string ns, object extensionObject)
{
Namespace = ns;
ExtensionObject = extensionObject;
}
public string Namespace { get; private set; }
public object ExtensionObject { get; private set; }
}
}

View File

@@ -1,33 +0,0 @@
using System;
using System.Security.Permissions;
using System.Web;
namespace Umbraco.Core.Macros
{
/// <summary>
/// Allows App_Code XSLT extensions to be declared using the [XsltExtension] class attribute.
/// </summary>
/// <remarks>
/// An optional XML namespace can be specified using [XsltExtension("MyNamespace")].
/// </remarks>
[AttributeUsage(AttributeTargets.Class)]
public class XsltExtensionAttribute : Attribute
{
public XsltExtensionAttribute()
{
Namespace = String.Empty;
}
public XsltExtensionAttribute(string ns)
{
Namespace = ns;
}
public string Namespace { get; set; }
public override string ToString()
{
return Namespace;
}
}
}

View File

@@ -1,12 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Macros
{
internal class XsltExtensionCollection : BuilderCollectionBase<XsltExtension>
{
public XsltExtensionCollection(IEnumerable<XsltExtension> items)
: base(items)
{ }
}
}

View File

@@ -1,78 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LightInject;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Macros
{
// that one is special since it's not initialized with XsltExtension types, but with Xslt extension object types,
// which are then wrapped in an XsltExtension object when the collection is created. so, cannot really inherit
// from (Lazy)CollectionBuilderBase and have to re-implement it. but almost everything is copied from CollectionBuilderBase.
internal class XsltExtensionCollectionBuilder : ICollectionBuilder<XsltExtensionCollection, XsltExtension>
{
private readonly IServiceContainer _container;
private readonly List<Func<IEnumerable<Type>>> _producers = new List<Func<IEnumerable<Type>>>();
private readonly object _locker = new object();
private ServiceRegistration[] _registrations;
public XsltExtensionCollectionBuilder(IServiceContainer container)
{
_container = container;
// register the collection
container.Register(_ => CreateCollection(), new PerContainerLifetime());
}
public static XsltExtensionCollectionBuilder Register(IServiceContainer container)
{
// register the builder - per container
var builderLifetime = new PerContainerLifetime();
container.Register<XsltExtensionCollectionBuilder>(builderLifetime);
return container.GetInstance<XsltExtensionCollectionBuilder>();
}
public XsltExtensionCollectionBuilder AddExtensionObjectProducer(Func<IEnumerable<Type>> producer)
{
lock (_locker)
{
if (_registrations != null)
throw new InvalidOperationException("Cannot configure a collection builder after its types have been resolved.");
_producers.Add(producer);
}
return this;
}
private void RegisterTypes()
{
lock (_locker)
{
if (_registrations != null) return;
var prefix = GetType().FullName + "_";
var i = 0;
foreach (var type in _producers.SelectMany(x => x()).Distinct())
{
var name = $"{prefix}{i++:00000}";
_container.Register(type, type, name);
}
_registrations = _container.AvailableServices
.Where(x => x.ServiceName.StartsWith(prefix))
.OrderBy(x => x.ServiceName)
.ToArray();
}
}
public XsltExtensionCollection CreateCollection()
{
RegisterTypes(); // will do it only once
var exts = _registrations.SelectMany(r => r.ServiceType.GetCustomAttributes<XsltExtensionAttribute>(true)
.Select(a => new XsltExtension(a.Namespace.IfNullOrWhiteSpace(r.ServiceType.FullName), _container.GetInstance(r.ServiceType, r.ServiceName))));
return new XsltExtensionCollection(exts);
}
}
}

View File

@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Media
{
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
// TypeLoader is asked to find types implementing this interface it will fall back
// to a complete scan.
[Obsolete("IImageUrlProvider is no longer used and will be removed in future versions")]
public interface IImageUrlProvider // IDiscoverable
{
string Name { get; }
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
string GetImageUrlFromFileName(string specifiedSrc, IDictionary<string, string> parameters);
}
}

View File

@@ -1,16 +0,0 @@
using System;
namespace Umbraco.Core.Media
{
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
// TypeLoader is asked to find types implementing this interface it will fall back
// to a complete scan.
[Obsolete("Thumbnails are generated by ImageProcessor, use that instead")]
public interface IThumbnailProvider // : IDiscoverable
{
bool CanProvideThumbnail(string fileUrl);
string GetThumbnailUrl(string fileUrl);
}
}

View File

@@ -41,9 +41,9 @@ namespace Umbraco.Core.Media
/// </summary> /// </summary>
/// <param name="content">The content item.</param> /// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</param> /// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="languageId">Variation language.</param> /// <param name="culture">Variation language.</param>
/// <param name="segment">Variation segment.</param> /// <param name="segment">Variation segment.</param>
public void Reset(IContentBase content, string propertyTypeAlias, int? languageId, string segment) public void Reset(IContentBase content, string propertyTypeAlias, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias)); if (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias));
@@ -53,7 +53,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing if (autoFillConfig == null) return; // nothing
// reset // reset
Reset(content, autoFillConfig, languageId, segment); Reset(content, autoFillConfig, culture, segment);
} }
/// <summary> /// <summary>
@@ -61,14 +61,14 @@ namespace Umbraco.Core.Media
/// </summary> /// </summary>
/// <param name="content">The content item.</param> /// <param name="content">The content item.</param>
/// <param name="autoFillConfig">The auto-fill configuration.</param> /// <param name="autoFillConfig">The auto-fill configuration.</param>
/// <param name="languageId">Variation language.</param> /// <param name="culture">Variation language.</param>
/// <param name="segment">Variation segment.</param> /// <param name="segment">Variation segment.</param>
public void Reset(IContentBase content, IImagingAutoFillUploadField autoFillConfig, int? languageId, string segment) public void Reset(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig)); if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
ResetProperties(content, autoFillConfig, languageId, segment); ResetProperties(content, autoFillConfig, culture, segment);
} }
/// <summary> /// <summary>
@@ -77,9 +77,9 @@ namespace Umbraco.Core.Media
/// <param name="content">The content item.</param> /// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</param> /// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param> /// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="languageId">Variation language.</param> /// <param name="culture">Variation language.</param>
/// <param name="segment">Variation segment.</param> /// <param name="segment">Variation segment.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, int? languageId, string segment) public void Populate(IContentBase content, string propertyTypeAlias, string filepath, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias)); if (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias));
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing if (autoFillConfig == null) return; // nothing
// populate // populate
Populate(content, autoFillConfig, filepath, languageId, segment); Populate(content, autoFillConfig, filepath, culture, segment);
} }
/// <summary> /// <summary>
@@ -102,9 +102,9 @@ namespace Umbraco.Core.Media
/// <param name="propertyTypeAlias">The property type alias.</param> /// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param> /// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param> /// <param name="filestream">The stream containing the file data.</param>
/// <param name="languageId">Variation language.</param> /// <param name="culture">Variation language.</param>
/// <param name="segment">Variation segment.</param> /// <param name="segment">Variation segment.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, int? languageId, string segment) public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias)); if (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias));
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing if (autoFillConfig == null) return; // nothing
// populate // populate
Populate(content, autoFillConfig, filepath, filestream, languageId, segment); Populate(content, autoFillConfig, filepath, filestream, culture, segment);
} }
/// <summary> /// <summary>
@@ -127,9 +127,9 @@ namespace Umbraco.Core.Media
/// <param name="autoFillConfig">The auto-fill configuration.</param> /// <param name="autoFillConfig">The auto-fill configuration.</param>
/// <param name="filepath">The filesystem path to the uploaded file.</param> /// <param name="filepath">The filesystem path to the uploaded file.</param>
/// <remarks>The <paramref name="filepath"/> parameter is the path relative to the filesystem.</remarks> /// <remarks>The <paramref name="filepath"/> parameter is the path relative to the filesystem.</remarks>
/// <param name="languageId">Variation language.</param> /// <param name="culture">Variation language.</param>
/// <param name="segment">Variation segment.</param> /// <param name="segment">Variation segment.</param>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, int? languageId, string segment) public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig)); if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
@@ -137,7 +137,7 @@ namespace Umbraco.Core.Media
// no file = reset, file = auto-fill // no file = reset, file = auto-fill
if (filepath.IsNullOrWhiteSpace()) if (filepath.IsNullOrWhiteSpace())
{ {
ResetProperties(content, autoFillConfig, languageId, segment); ResetProperties(content, autoFillConfig, culture, segment);
} }
else else
{ {
@@ -148,13 +148,13 @@ namespace Umbraco.Core.Media
{ {
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.'); var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null; var size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension, languageId, segment); SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error(typeof(UploadAutoFillProperties), $"Could not populate upload auto-fill properties for file \"{filepath}\".", ex); _logger.Error(typeof(UploadAutoFillProperties), $"Could not populate upload auto-fill properties for file \"{filepath}\".", ex);
ResetProperties(content, autoFillConfig, languageId, segment); ResetProperties(content, autoFillConfig, culture, segment);
} }
} }
} }
@@ -166,9 +166,9 @@ namespace Umbraco.Core.Media
/// <param name="autoFillConfig"></param> /// <param name="autoFillConfig"></param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param> /// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param> /// <param name="filestream">The stream containing the file data.</param>
/// <param name="languageId">Variation language.</param> /// <param name="culture">Variation language.</param>
/// <param name="segment">Variation segment.</param> /// <param name="segment">Variation segment.</param>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, int? languageId, string segment) public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig)); if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
@@ -176,50 +176,50 @@ namespace Umbraco.Core.Media
// no file = reset, file = auto-fill // no file = reset, file = auto-fill
if (filepath.IsNullOrWhiteSpace() || filestream == null) if (filepath.IsNullOrWhiteSpace() || filestream == null)
{ {
ResetProperties(content, autoFillConfig, languageId, segment); ResetProperties(content, autoFillConfig, culture, segment);
} }
else else
{ {
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.'); var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?)_mediaFileSystem.GetDimensions(filestream) : null; var size = _mediaFileSystem.IsImageFile(extension) ? (Size?)_mediaFileSystem.GetDimensions(filestream) : null;
SetProperties(content, autoFillConfig, size, filestream.Length, extension, languageId, segment); SetProperties(content, autoFillConfig, size, filestream.Length, extension, culture, segment);
} }
} }
private static void SetProperties(IContentBase content, IImagingAutoFillUploadField autoFillConfig, Size? size, long length, string extension, int? languageId, string segment) private static void SetProperties(IContentBase content, IImagingAutoFillUploadField autoFillConfig, Size? size, long length, string extension, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig)); if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
if (content.Properties.Contains(autoFillConfig.WidthFieldAlias)) if (content.Properties.Contains(autoFillConfig.WidthFieldAlias))
content.Properties[autoFillConfig.WidthFieldAlias].SetValue(size.HasValue ? size.Value.Width.ToInvariantString() : string.Empty, languageId, segment); content.Properties[autoFillConfig.WidthFieldAlias].SetValue(size.HasValue ? size.Value.Width.ToInvariantString() : string.Empty, culture, segment);
if (content.Properties.Contains(autoFillConfig.HeightFieldAlias)) if (content.Properties.Contains(autoFillConfig.HeightFieldAlias))
content.Properties[autoFillConfig.HeightFieldAlias].SetValue(size.HasValue ? size.Value.Height.ToInvariantString() : string.Empty, languageId, segment); content.Properties[autoFillConfig.HeightFieldAlias].SetValue(size.HasValue ? size.Value.Height.ToInvariantString() : string.Empty, culture, segment);
if (content.Properties.Contains(autoFillConfig.LengthFieldAlias)) if (content.Properties.Contains(autoFillConfig.LengthFieldAlias))
content.Properties[autoFillConfig.LengthFieldAlias].SetValue(length, languageId, segment); content.Properties[autoFillConfig.LengthFieldAlias].SetValue(length, culture, segment);
if (content.Properties.Contains(autoFillConfig.ExtensionFieldAlias)) if (content.Properties.Contains(autoFillConfig.ExtensionFieldAlias))
content.Properties[autoFillConfig.ExtensionFieldAlias].SetValue(extension, languageId, segment); content.Properties[autoFillConfig.ExtensionFieldAlias].SetValue(extension, culture, segment);
} }
private static void ResetProperties(IContentBase content, IImagingAutoFillUploadField autoFillConfig, int? languageId, string segment) private static void ResetProperties(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string culture, string segment)
{ {
if (content == null) throw new ArgumentNullException(nameof(content)); if (content == null) throw new ArgumentNullException(nameof(content));
if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig)); if (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
if (content.Properties.Contains(autoFillConfig.WidthFieldAlias)) if (content.Properties.Contains(autoFillConfig.WidthFieldAlias))
content.Properties[autoFillConfig.WidthFieldAlias].SetValue(string.Empty, languageId, segment); content.Properties[autoFillConfig.WidthFieldAlias].SetValue(string.Empty, culture, segment);
if (content.Properties.Contains(autoFillConfig.HeightFieldAlias)) if (content.Properties.Contains(autoFillConfig.HeightFieldAlias))
content.Properties[autoFillConfig.HeightFieldAlias].SetValue(string.Empty, languageId, segment); content.Properties[autoFillConfig.HeightFieldAlias].SetValue(string.Empty, culture, segment);
if (content.Properties.Contains(autoFillConfig.LengthFieldAlias)) if (content.Properties.Contains(autoFillConfig.LengthFieldAlias))
content.Properties[autoFillConfig.LengthFieldAlias].SetValue(string.Empty, languageId, segment); content.Properties[autoFillConfig.LengthFieldAlias].SetValue(string.Empty, culture, segment);
if (content.Properties.Contains(autoFillConfig.ExtensionFieldAlias)) if (content.Properties.Contains(autoFillConfig.ExtensionFieldAlias))
content.Properties[autoFillConfig.ExtensionFieldAlias].SetValue(string.Empty, languageId, segment); content.Properties[autoFillConfig.ExtensionFieldAlias].SetValue(string.Empty, culture, segment);
} }
} }
} }

View File

@@ -82,7 +82,8 @@ namespace Umbraco.Core.Migrations.Install
typeof (UserLoginDto), typeof (UserLoginDto),
typeof (ConsentDto), typeof (ConsentDto),
typeof (AuditEntryDto), typeof (AuditEntryDto),
typeof (ContentVersionCultureVariationDto) typeof (ContentVersionCultureVariationDto),
typeof (DocumentCultureVariationDto)
}; };
/// <summary> /// <summary>

View File

@@ -116,10 +116,12 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain<SuperZero>("{9DF05B77-11D1-475C-A00A-B656AF7E0908}"); Chain<SuperZero>("{9DF05B77-11D1-475C-A00A-B656AF7E0908}");
Chain<PropertyEditorsMigration>("{6FE3EF34-44A0-4992-B379-B40BC4EF1C4D}"); Chain<PropertyEditorsMigration>("{6FE3EF34-44A0-4992-B379-B40BC4EF1C4D}");
Chain<LanguageColumns>("{7F59355A-0EC9-4438-8157-EB517E6D2727}"); Chain<LanguageColumns>("{7F59355A-0EC9-4438-8157-EB517E6D2727}");
Chain<AddContentVariationTable>("{66B6821A-0DE3-4DF8-A6A4-65ABD211EDDE}"); Chain<AddVariationTables1A>("{66B6821A-0DE3-4DF8-A6A4-65ABD211EDDE}");
Chain<AddVariationTables2>("{49506BAE-CEBB-4431-A1A6-24AD6EBBBC57}");
Chain<RefactorMacroColumns>("{083A9894-903D-41B7-B6B3-9EAF2D4CCED0}");
// must chain to v8 final state (see at end of file) // must chain to v8 final state (see at end of file)
Chain("{941B2ABA-2D06-4E04-81F5-74224F1DB037}"); Chain("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
// UPGRADE FROM 7, MORE RECENT // UPGRADE FROM 7, MORE RECENT
@@ -201,12 +203,19 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain<RenamePreviewFolder>("{79591E91-01EA-43F7-AC58-7BD286DB1E77}"); Chain<RenamePreviewFolder>("{79591E91-01EA-43F7-AC58-7BD286DB1E77}");
// 8.0.0 // 8.0.0
Chain<AddContentVariationTable>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}"); // AddVariationTables1 has been superceeded by AddVariationTables2
//Chain<AddVariationTables1>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}");
Chain<AddVariationTables2>("{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
// however, need to take care of ppl in post-AddVariationTables1 state
Add<AddVariationTables1A>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}", "{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
Chain<RefactorMacroColumns>("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
// FINAL STATE - MUST MATCH LAST ONE ABOVE ! // FINAL STATE - MUST MATCH LAST ONE ABOVE !
// whenever this changes, update all references in this file! // whenever this changes, update all references in this file!
Add(string.Empty, "{941B2ABA-2D06-4E04-81F5-74224F1DB037}"); Add(string.Empty, "{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
} }
} }
} }

View File

@@ -0,0 +1,47 @@
using System;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class AddVariationTables1A : MigrationBase
{
public AddVariationTables1A(IMigrationContext context)
: base(context)
{ }
// note - original AddVariationTables1 just did
// Create.Table<ContentVersionCultureVariationDto>().Do();
//
// this is taking care of ppl left in this state
public override void Migrate()
{
// note - original AddVariationTables1 just did
// Create.Table<ContentVersionCultureVariationDto>().Do();
//
// it's been deprecated, not part of the main upgrade path,
// but we need to take care of ppl caught into the state
// was not used
Delete.Column("available").FromTable(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation).Do();
// was not used
Delete.Column("availableDate").FromTable(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation).Do();
//special trick to add the column without constraints and return the sql to add them later
AddColumn<ContentVersionCultureVariationDto>("date", out var sqls);
//now we need to update the new column with some values because this column doesn't allow NULL values
Update.Table(ContentVersionCultureVariationDto.TableName).Set(new {date = DateTime.Now}).AllRows().Do();
//now apply constraints (NOT NULL) to new table
foreach (var sql in sqls) Execute.Sql(sql).Do();
// name, languageId are now non-nullable
AlterColumn<ContentVersionCultureVariationDto>(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation, "name");
AlterColumn<ContentVersionCultureVariationDto>(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation, "languageId");
Create.Table<DocumentCultureVariationDto>().Do();
// fixme - data migration?
}
}
}

View File

@@ -1,16 +1,18 @@
using Umbraco.Core.Persistence.Dtos; using System;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{ {
public class AddContentVariationTable : MigrationBase public class AddVariationTables2 : MigrationBase
{ {
public AddContentVariationTable(IMigrationContext context) public AddVariationTables2(IMigrationContext context)
: base(context) : base(context)
{ } { }
public override void Migrate() public override void Migrate()
{ {
Create.Table<ContentVersionCultureVariationDto>().Do(); Create.Table<ContentVersionCultureVariationDto>().Do();
Create.Table<DocumentCultureVariationDto>().Do();
// fixme - data migration? // fixme - data migration?
} }

View File

@@ -0,0 +1,43 @@
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class RefactorMacroColumns : MigrationBase
{
public RefactorMacroColumns(IMigrationContext context)
: base(context)
{ }
public override void Migrate()
{
if (ColumnExists(Constants.DatabaseSchema.Tables.Macro, "macroXSLT"))
{
//special trick to add the column without constraints and return the sql to add them later
AddColumn<MacroDto>("macroType", out var sqls1);
//now we need to update the new column with some values because this column doesn't allow NULL values
Update.Table(Constants.DatabaseSchema.Tables.Macro).Set(new { macroType = (int)MacroTypes.Unknown}).AllRows().Do();
//now apply constraints (NOT NULL) to new table
foreach (var sql in sqls1) Execute.Sql(sql).Do();
//special trick to add the column without constraints and return the sql to add them later
AddColumn<MacroDto>("macroSource", out var sqls2);
//populate the new macroSource column with legacy data
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroXSLT, macroType = {(int)MacroTypes.Unknown} WHERE macroXSLT IS NOT NULL").Do();
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroScriptAssembly, macroType = {(int)MacroTypes.Unknown} WHERE macroScriptAssembly IS NOT NULL").Do();
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroScriptType, macroType = {(int)MacroTypes.UserControl} WHERE macroScriptType IS NOT NULL").Do();
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroPython, macroType = {(int)MacroTypes.PartialView} WHERE macroPython IS NOT NULL").Do();
//now apply constraints (NOT NULL) to new table
foreach (var sql in sqls2) Execute.Sql(sql).Do();
//now remove these old columns
Delete.Column("macroXSLT").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
Delete.Column("macroScriptAssembly").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
Delete.Column("macroScriptType").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
Delete.Column("macroPython").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
}
}
}
}

View File

@@ -67,13 +67,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
.Do(); .Do();
} }
private bool ColumnExists(string tableName, string columnName)
{
// that's ok even on MySql
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray();
return columns.Any(x => x.TableName.InvariantEquals(tableName) && x.ColumnName.InvariantEquals(columnName));
}
private void RemoveDuplicates() private void RemoveDuplicates()
{ {
const string sql = @"delete from cmsPreviewXml where versionId in ( const string sql = @"delete from cmsPreviewXml where versionId in (

View File

@@ -20,7 +20,8 @@ namespace Umbraco.Core.Models
private PublishedState _publishedState; private PublishedState _publishedState;
private DateTime? _releaseDate; private DateTime? _releaseDate;
private DateTime? _expireDate; private DateTime? _expireDate;
private Dictionary<int, string> _publishNames; private Dictionary<string, (string Name, DateTime Date)> _publishInfos;
private HashSet<string> _edited;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>(); private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
@@ -30,8 +31,8 @@ namespace Umbraco.Core.Models
/// <param name="name">Name of the content</param> /// <param name="name">Name of the content</param>
/// <param name="parent">Parent <see cref="IContent"/> object</param> /// <param name="parent">Parent <see cref="IContent"/> object</param>
/// <param name="contentType">ContentType for the current Content object</param> /// <param name="contentType">ContentType for the current Content object</param>
public Content(string name, IContent parent, IContentType contentType) public Content(string name, IContent parent, IContentType contentType, string culture = null)
: this(name, parent, contentType, new PropertyCollection()) : this(name, parent, contentType, new PropertyCollection(), culture)
{ } { }
/// <summary> /// <summary>
@@ -41,8 +42,8 @@ namespace Umbraco.Core.Models
/// <param name="parent">Parent <see cref="IContent"/> object</param> /// <param name="parent">Parent <see cref="IContent"/> object</param>
/// <param name="contentType">ContentType for the current Content object</param> /// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param> /// <param name="properties">Collection of properties</param>
public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties) public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parent, contentType, properties) : base(name, parent, contentType, properties, culture)
{ {
_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); _contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
_publishedState = PublishedState.Unpublished; _publishedState = PublishedState.Unpublished;
@@ -55,8 +56,8 @@ namespace Umbraco.Core.Models
/// <param name="name">Name of the content</param> /// <param name="name">Name of the content</param>
/// <param name="parentId">Id of the Parent content</param> /// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param> /// <param name="contentType">ContentType for the current Content object</param>
public Content(string name, int parentId, IContentType contentType) public Content(string name, int parentId, IContentType contentType, string culture = null)
: this(name, parentId, contentType, new PropertyCollection()) : this(name, parentId, contentType, new PropertyCollection(), culture)
{ } { }
/// <summary> /// <summary>
@@ -66,8 +67,8 @@ namespace Umbraco.Core.Models
/// <param name="parentId">Id of the Parent content</param> /// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param> /// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param> /// <param name="properties">Collection of properties</param>
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties) public Content(string name, int parentId, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parentId, contentType, properties) : base(name, parentId, contentType, properties, culture)
{ {
_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); _contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
_publishedState = PublishedState.Unpublished; _publishedState = PublishedState.Unpublished;
@@ -195,73 +196,116 @@ namespace Umbraco.Core.Models
[IgnoreDataMember] [IgnoreDataMember]
public ITemplate PublishTemplate { get; internal set; } public ITemplate PublishTemplate { get; internal set; }
[IgnoreDataMember] [IgnoreDataMember]
public string PublishName { get; internal set; } public string PublishName { get; internal set; }
/// <inheritdoc/> // sets publish infos
[IgnoreDataMember]
public IReadOnlyDictionary<int, string> PublishNames => _publishNames ?? NoNames;
/// <inheritdoc/>
public string GetPublishName(int? languageId)
{
if (languageId == null) return PublishName;
if (_publishNames == null) return null;
return _publishNames.TryGetValue(languageId.Value, out var name) ? name : null;
}
// sets a publish name
// internal for repositories // internal for repositories
internal void SetPublishName(int? languageId, string name) // clear by clearing name
{ internal void SetPublishInfos(string culture, string name, DateTime date)
if (string.IsNullOrWhiteSpace(name)) {
throw new ArgumentNullOrEmptyException(nameof(name)); if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullOrEmptyException(nameof(name));
if (languageId == null)
// this is the only place where we set PublishName (apart from factories etc), and we must ensure
// that we do have an invariant name, as soon as we have a variant name, else we would end up not
// being able to publish - and not being able to change the name, as PublishName is readonly.
// see also: DocumentRepository.EnsureInvariantNameValues() - which deals with Name.
// see also: U4-11286
if (culture == null || string.IsNullOrEmpty(PublishName))
{ {
PublishName = name; PublishName = name;
return; PublishDate = date;
} }
// private method, assume that culture is valid if (culture != null)
{
if (_publishNames == null) // private method, assume that culture is valid
_publishNames = new Dictionary<int, string>();
_publishNames[languageId.Value] = name;
}
// clears a publish name if (_publishInfos == null)
private void ClearPublishName(int? languageId) _publishInfos = new Dictionary<string, (string Name, DateTime Date)>(StringComparer.OrdinalIgnoreCase);
_publishInfos[culture] = (name, date);
}
}
/// <inheritdoc/>
[IgnoreDataMember]
//public IReadOnlyDictionary<string, string> PublishNames => _publishNames ?? NoNames;
public IReadOnlyDictionary<string, string> PublishNames => _publishInfos?.ToDictionary(x => x.Key, x => x.Value.Name) ?? NoNames;
/// <inheritdoc/>
public string GetPublishName(string culture)
{ {
if (languageId == null) if (culture == null) return PublishName;
if (_publishInfos == null) return null;
return _publishInfos.TryGetValue(culture, out var infos) ? infos.Name : null;
}
// clears a publish name
private void ClearPublishName(string culture)
{
if (culture == null)
{ {
PublishName = null; PublishName = null;
return; return;
} }
if (_publishNames == null) return; if (_publishInfos == null) return;
_publishNames.Remove(languageId.Value); _publishInfos.Remove(culture);
if (_publishNames.Count == 0) if (_publishInfos.Count == 0)
_publishNames = null; _publishInfos = null;
} }
// clears all publish names // clears all publish names
private void ClearPublishNames() private void ClearPublishNames()
{ {
PublishName = null; PublishName = null;
_publishNames = null; _publishInfos = null;
} }
/// <inheritdoc /> /// <inheritdoc />
public bool IsCultureAvailable(int? languageId) public bool IsCulturePublished(string culture)
=> !string.IsNullOrWhiteSpace(GetName(languageId)); => !string.IsNullOrWhiteSpace(GetPublishName(culture));
/// <inheritdoc /> /// <inheritdoc />
public bool IsCulturePublished(int? languageId) public DateTime GetDateCulturePublished(string culture)
=> !string.IsNullOrWhiteSpace(GetPublishName(languageId)); {
if (_publishInfos != null && _publishInfos.TryGetValue(culture, out var infos))
return infos.Date;
throw new InvalidOperationException($"Culture \"{culture}\" is not published.");
}
/// <inheritdoc />
public IEnumerable<string> PublishedCultures => _publishInfos?.Keys ?? Enumerable.Empty<string>();
/// <inheritdoc />
public bool IsCultureEdited(string culture)
{
return string.IsNullOrWhiteSpace(GetPublishName(culture)) || (_edited != null && _edited.Contains(culture));
}
// sets a publish edited
internal void SetCultureEdited(string culture)
{
if (_edited == null)
_edited = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
_edited.Add(culture);
}
// sets all publish edited
internal void SetCultureEdited(IEnumerable<string> cultures)
{
_edited = new HashSet<string>(cultures, StringComparer.OrdinalIgnoreCase);
}
/// <inheritdoc />
public IEnumerable<string> EditedCultures => Names.Keys.Where(IsCultureEdited);
/// <inheritdoc />
public IEnumerable<string> AvailableCultures => Names.Keys;
[IgnoreDataMember] [IgnoreDataMember]
public int PublishedVersionId { get; internal set; } public int PublishedVersionId { get; internal set; }
@@ -269,62 +313,80 @@ namespace Umbraco.Core.Models
public bool Blueprint { get; internal set; } public bool Blueprint { get; internal set; }
/// <inheritdoc /> /// <inheritdoc />
public virtual bool PublishAllValues() public virtual bool TryPublishAllValues()
{ {
// the values we want to publish should be valid // the values we want to publish should be valid
if (ValidateAll().Any()) if (ValidateAll().Any())
return false; return false; //fixme this should return an attempt with error results
// Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations.
if (string.IsNullOrWhiteSpace(Name))
throw new InvalidOperationException($"Cannot publish invariant culture without a name.");
PublishName = Name;
var now = DateTime.Now;
foreach (var (culture, name) in Names)
{
if (string.IsNullOrWhiteSpace(name))
return false; //fixme this should return an attempt with error results
SetPublishInfos(culture, name, now);
}
// property.PublishAllValues only deals with supported variations (if any) // property.PublishAllValues only deals with supported variations (if any)
foreach (var property in Properties) foreach (var property in Properties)
property.PublishAllValues(); property.PublishAllValues();
// Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations.
PublishName = Name;
foreach (var (languageId, name) in Names)
SetPublishName(languageId, name);
_publishedState = PublishedState.Publishing; _publishedState = PublishedState.Publishing;
return true; return true;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual bool PublishValues(int? languageId = null, string segment = null) public virtual bool TryPublishValues(string culture = null, string segment = null)
{ {
// the variation should be supported by the content type // the variation should be supported by the content type
ContentType.ValidateVariation(languageId, segment, throwIfInvalid: true); ContentType.ValidateVariation(culture, segment, throwIfInvalid: true);
// the values we want to publish should be valid // the values we want to publish should be valid
if (Validate(languageId, segment).Any()) if (Validate(culture, segment).Any())
return false; return false; //fixme this should return an attempt with error results
// property.PublishValue throws on invalid variation, so filter them out
foreach (var property in Properties.Where(x => x.PropertyType.ValidateVariation(languageId, segment, throwIfInvalid: false)))
property.PublishValue(languageId, segment);
// Name and PublishName are managed by the repository, but Names and PublishNames // Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations. // must be managed here as they depend on the existing / supported variations.
SetPublishName(languageId, GetName(languageId)); if (segment == null)
{
var name = GetName(culture);
if (string.IsNullOrWhiteSpace(name))
return false; //fixme this should return an attempt with error results
SetPublishInfos(culture, name, DateTime.Now);
}
// property.PublishValue throws on invalid variation, so filter them out
foreach (var property in Properties.Where(x => x.PropertyType.ValidateVariation(culture, segment, throwIfInvalid: false)))
property.PublishValue(culture, segment);
_publishedState = PublishedState.Publishing; _publishedState = PublishedState.Publishing;
return true; return true;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual bool PublishCultureValues(int? languageId = null) public virtual bool PublishCultureValues(string culture = null)
{ {
// the values we want to publish should be valid // the values we want to publish should be valid
if (ValidateCulture(languageId).Any()) if (ValidateCulture(culture).Any())
return false; return false;
// Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations.
var name = GetName(culture);
if (string.IsNullOrWhiteSpace(name))
throw new InvalidOperationException($"Cannot publish {culture ?? "invariant"} culture without a name.");
SetPublishInfos(culture, name, DateTime.Now);
// property.PublishCultureValues only deals with supported variations (if any) // property.PublishCultureValues only deals with supported variations (if any)
foreach (var property in Properties) foreach (var property in Properties)
property.PublishCultureValues(languageId); property.PublishCultureValues(culture);
// Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations.
SetPublishName(languageId, GetName(languageId));
_publishedState = PublishedState.Publishing; _publishedState = PublishedState.Publishing;
return true; return true;
@@ -339,42 +401,42 @@ namespace Umbraco.Core.Models
// Name and PublishName are managed by the repository, but Names and PublishNames // Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations. // must be managed here as they depend on the existing / supported variations.
ClearPublishNames(); ClearPublishNames();
_publishedState = PublishedState.Publishing; _publishedState = PublishedState.Publishing;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual void ClearPublishedValues(int? languageId = null, string segment = null) public virtual void ClearPublishedValues(string culture = null, string segment = null)
{ {
// the variation should be supported by the content type // the variation should be supported by the content type
ContentType.ValidateVariation(languageId, segment, throwIfInvalid: true); ContentType.ValidateVariation(culture, segment, throwIfInvalid: true);
// property.ClearPublishedValue throws on invalid variation, so filter them out // property.ClearPublishedValue throws on invalid variation, so filter them out
foreach (var property in Properties.Where(x => x.PropertyType.ValidateVariation(languageId, segment, throwIfInvalid: false))) foreach (var property in Properties.Where(x => x.PropertyType.ValidateVariation(culture, segment, throwIfInvalid: false)))
property.ClearPublishedValue(languageId, segment); property.ClearPublishedValue(culture, segment);
// Name and PublishName are managed by the repository, but Names and PublishNames // Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations. // must be managed here as they depend on the existing / supported variations.
ClearPublishName(languageId); ClearPublishName(culture);
_publishedState = PublishedState.Publishing; _publishedState = PublishedState.Publishing;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual void ClearCulturePublishedValues(int? languageId = null) public virtual void ClearCulturePublishedValues(string culture = null)
{ {
// property.ClearPublishedCultureValues only deals with supported variations (if any) // property.ClearPublishedCultureValues only deals with supported variations (if any)
foreach (var property in Properties) foreach (var property in Properties)
property.ClearPublishedCultureValues(languageId); property.ClearPublishedCultureValues(culture);
// Name and PublishName are managed by the repository, but Names and PublishNames // Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations. // must be managed here as they depend on the existing / supported variations.
ClearPublishName(languageId); ClearPublishName(culture);
_publishedState = PublishedState.Publishing; _publishedState = PublishedState.Publishing;
} }
private bool CopyingFromSelf(IContent other) private bool CopyingFromSelf(IContent other)
{ {
// copying from the same Id and VersionPk // copying from the same Id and VersionPk
@@ -397,8 +459,8 @@ namespace Umbraco.Core.Models
// clear all existing properties // clear all existing properties
foreach (var property in Properties) foreach (var property in Properties)
foreach (var pvalue in property.Values) foreach (var pvalue in property.Values)
if (property.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) if (property.PropertyType.ValidateVariation(pvalue.Culture, pvalue.Segment, false))
property.SetValue(null, pvalue.LanguageId, pvalue.Segment); property.SetValue(null, pvalue.Culture, pvalue.Segment);
// copy other properties // copy other properties
var otherProperties = other.Properties; var otherProperties = other.Properties;
@@ -407,22 +469,22 @@ namespace Umbraco.Core.Models
var alias = otherProperty.PropertyType.Alias; var alias = otherProperty.PropertyType.Alias;
foreach (var pvalue in otherProperty.Values) foreach (var pvalue in otherProperty.Values)
{ {
if (!otherProperty.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) if (!otherProperty.PropertyType.ValidateVariation(pvalue.Culture, pvalue.Segment, false))
continue; continue;
var value = published ? pvalue.PublishedValue : pvalue.EditedValue; var value = published ? pvalue.PublishedValue : pvalue.EditedValue;
SetValue(alias, value, pvalue.LanguageId, pvalue.Segment); SetValue(alias, value, pvalue.Culture, pvalue.Segment);
} }
} }
// copy names // copy names
ClearNames(); ClearNames();
foreach (var (languageId, name) in other.Names) foreach (var (languageId, name) in other.Names)
SetName(languageId, name); SetName(languageId, name);
Name = other.Name; Name = other.Name;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual void CopyValues(IContent other, int? languageId = null, string segment = null) public virtual void CopyValues(IContent other, string culture = null, string segment = null)
{ {
if (other.ContentTypeId != ContentTypeId) if (other.ContentTypeId != ContentTypeId)
throw new InvalidOperationException("Cannot copy values from a different content type."); throw new InvalidOperationException("Cannot copy values from a different content type.");
@@ -437,31 +499,31 @@ namespace Umbraco.Core.Models
// clear all existing properties // clear all existing properties
foreach (var property in Properties) foreach (var property in Properties)
{ {
if (!property.PropertyType.ValidateVariation(languageId, segment, false)) if (!property.PropertyType.ValidateVariation(culture, segment, false))
continue; continue;
foreach (var pvalue in property.Values) foreach (var pvalue in property.Values)
if (pvalue.LanguageId == languageId && pvalue.Segment == segment) if (pvalue.Culture.InvariantEquals(culture) && pvalue.Segment.InvariantEquals(segment))
property.SetValue(null, pvalue.LanguageId, pvalue.Segment); property.SetValue(null, pvalue.Culture, pvalue.Segment);
} }
// copy other properties // copy other properties
var otherProperties = other.Properties; var otherProperties = other.Properties;
foreach (var otherProperty in otherProperties) foreach (var otherProperty in otherProperties)
{ {
if (!otherProperty.PropertyType.ValidateVariation(languageId, segment, false)) if (!otherProperty.PropertyType.ValidateVariation(culture, segment, false))
continue; continue;
var alias = otherProperty.PropertyType.Alias; var alias = otherProperty.PropertyType.Alias;
SetValue(alias, otherProperty.GetValue(languageId, segment, published), languageId, segment); SetValue(alias, otherProperty.GetValue(culture, segment, published), culture, segment);
} }
// copy name // copy name
SetName(languageId, other.GetName(languageId)); SetName(culture, other.GetName(culture));
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual void CopyCultureValues(IContent other, int? languageId = null) public virtual void CopyCultureValues(IContent other, string culture = null)
{ {
if (other.ContentTypeId != ContentTypeId) if (other.ContentTypeId != ContentTypeId)
throw new InvalidOperationException("Cannot copy values from a different content type."); throw new InvalidOperationException("Cannot copy values from a different content type.");
@@ -473,8 +535,8 @@ namespace Umbraco.Core.Models
// clear all existing properties // clear all existing properties
foreach (var property in Properties) foreach (var property in Properties)
foreach (var pvalue in property.Values) foreach (var pvalue in property.Values)
if (pvalue.LanguageId == languageId && property.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) if (pvalue.Culture.InvariantEquals(culture) && property.PropertyType.ValidateVariation(pvalue.Culture, pvalue.Segment, false))
property.SetValue(null, pvalue.LanguageId, pvalue.Segment); property.SetValue(null, pvalue.Culture, pvalue.Segment);
// copy other properties // copy other properties
var otherProperties = other.Properties; var otherProperties = other.Properties;
@@ -483,15 +545,15 @@ namespace Umbraco.Core.Models
var alias = otherProperty.PropertyType.Alias; var alias = otherProperty.PropertyType.Alias;
foreach (var pvalue in otherProperty.Values) foreach (var pvalue in otherProperty.Values)
{ {
if (pvalue.LanguageId != languageId || !otherProperty.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) if (pvalue.Culture != culture || !otherProperty.PropertyType.ValidateVariation(pvalue.Culture, pvalue.Segment, false))
continue; continue;
var value = published ? pvalue.PublishedValue : pvalue.EditedValue; var value = published ? pvalue.PublishedValue : pvalue.EditedValue;
SetValue(alias, value, pvalue.LanguageId, pvalue.Segment); SetValue(alias, value, pvalue.Culture, pvalue.Segment);
} }
} }
// copy name // copy name
SetName(languageId, other.GetName(languageId)); SetName(culture, other.GetName(culture));
} }
/// <summary> /// <summary>

View File

@@ -18,20 +18,20 @@ namespace Umbraco.Core.Models
[DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")] [DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")]
public abstract class ContentBase : TreeEntityBase, IContentBase public abstract class ContentBase : TreeEntityBase, IContentBase
{ {
protected static readonly Dictionary<int, string> NoNames = new Dictionary<int, string>(); protected static readonly Dictionary<string, string> NoNames = new Dictionary<string, string>();
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>(); private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private int _contentTypeId; private int _contentTypeId;
protected IContentTypeComposition ContentTypeBase; protected IContentTypeComposition ContentTypeBase;
private int _writerId; private int _writerId;
private PropertyCollection _properties; private PropertyCollection _properties;
private Dictionary<int, string> _names; private Dictionary<string, string> _names;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ContentBase"/> class. /// Initializes a new instance of the <see cref="ContentBase"/> class.
/// </summary> /// </summary>
protected ContentBase(string name, int parentId, IContentTypeComposition contentType, PropertyCollection properties) protected ContentBase(string name, int parentId, IContentTypeComposition contentType, PropertyCollection properties, string culture = null)
: this(name, contentType, properties) : this(name, contentType, properties, culture)
{ {
if (parentId == 0) throw new ArgumentOutOfRangeException(nameof(parentId)); if (parentId == 0) throw new ArgumentOutOfRangeException(nameof(parentId));
ParentId = parentId; ParentId = parentId;
@@ -40,22 +40,23 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ContentBase"/> class. /// Initializes a new instance of the <see cref="ContentBase"/> class.
/// </summary> /// </summary>
protected ContentBase(string name, IContentBase parent, IContentTypeComposition contentType, PropertyCollection properties) protected ContentBase(string name, IContentBase parent, IContentTypeComposition contentType, PropertyCollection properties, string culture = null)
: this(name, contentType, properties) : this(name, contentType, properties, culture)
{ {
if (parent == null) throw new ArgumentNullException(nameof(parent)); if (parent == null) throw new ArgumentNullException(nameof(parent));
SetParent(parent); SetParent(parent);
} }
private ContentBase(string name, IContentTypeComposition contentType, PropertyCollection properties) private ContentBase(string name, IContentTypeComposition contentType, PropertyCollection properties, string culture = null)
{ {
ContentTypeBase = contentType ?? throw new ArgumentNullException(nameof(contentType)); ContentTypeBase = contentType ?? throw new ArgumentNullException(nameof(contentType));
// initially, all new instances have // initially, all new instances have
Id = 0; // no identity Id = 0; // no identity
VersionId = 0; // no versions VersionId = 0; // no versions
SetName(culture, name);
Name = name;
_contentTypeId = contentType.Id; _contentTypeId = contentType.Id;
_properties = properties ?? throw new ArgumentNullException(nameof(properties)); _properties = properties ?? throw new ArgumentNullException(nameof(properties));
_properties.EnsurePropertyTypes(PropertyTypes); _properties.EnsurePropertyTypes(PropertyTypes);
@@ -67,7 +68,7 @@ namespace Umbraco.Core.Models
public readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId); public readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId);
public readonly PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties); public readonly PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.WriterId); public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.WriterId);
public readonly PropertyInfo NamesSelector = ExpressionHelper.GetPropertyInfo<ContentBase, IReadOnlyDictionary<int, string>>(x => x.Names); public readonly PropertyInfo NamesSelector = ExpressionHelper.GetPropertyInfo<ContentBase, IReadOnlyDictionary<string, string>>(x => x.Names);
} }
protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
@@ -121,71 +122,6 @@ namespace Umbraco.Core.Models
} }
} }
/// <inheritdoc />
[DataMember]
public virtual IReadOnlyDictionary<int, string> Names
{
get => _names ?? NoNames;
set
{
foreach (var (languageId, name) in value)
SetName(languageId, name);
}
}
/// <inheritdoc />
public virtual void SetName(int? languageId, string name)
{
if (string.IsNullOrWhiteSpace(name))
{
ClearName(languageId);
return;
}
if (languageId == null)
{
Name = name;
return;
}
if ((ContentTypeBase.Variations & (ContentVariation.CultureNeutral | ContentVariation.CultureSegment)) == 0)
throw new NotSupportedException("Content type does not support varying name by culture.");
if (_names == null)
_names = new Dictionary<int, string>();
_names[languageId.Value] = name;
OnPropertyChanged(Ps.Value.NamesSelector);
}
private void ClearName(int? languageId)
{
if (languageId == null)
{
Name = null;
return;
}
if (_names == null) return;
_names.Remove(languageId.Value);
if (_names.Count == 0)
_names = null;
}
protected virtual void ClearNames()
{
_names = null;
OnPropertyChanged(Ps.Value.NamesSelector);
}
/// <inheritdoc />
public virtual string GetName(int? languageId)
{
if (languageId == null) return Name;
if (_names == null) return null;
return _names.TryGetValue(languageId.Value, out var name) ? name : null;
}
/// <summary> /// <summary>
/// Gets the enumeration of property groups for the entity. /// Gets the enumeration of property groups for the entity.
/// fixme is a proxy, kill this /// fixme is a proxy, kill this
@@ -199,6 +135,79 @@ namespace Umbraco.Core.Models
/// </summary> /// </summary>
[IgnoreDataMember] [IgnoreDataMember]
public IEnumerable<PropertyType> PropertyTypes => ContentTypeBase.CompositionPropertyTypes; public IEnumerable<PropertyType> PropertyTypes => ContentTypeBase.CompositionPropertyTypes;
#region Cultures
/// <inheritdoc />
[DataMember]
public virtual IReadOnlyDictionary<string, string> Names
{
get => _names ?? NoNames;
set
{
foreach (var (culture, name) in value)
SetName(culture, name);
}
}
/// <inheritdoc />
public virtual void SetName(string culture, string name)
{
if (string.IsNullOrWhiteSpace(name))
{
ClearName(culture);
return;
}
if (culture == null)
{
Name = name;
return;
}
if (!ContentTypeBase.Variations.HasAny(ContentVariation.CultureNeutral | ContentVariation.CultureSegment))
throw new NotSupportedException("Content type does not support varying name by culture.");
if (_names == null)
_names = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
_names[culture] = name;
OnPropertyChanged(Ps.Value.NamesSelector);
}
/// <inheritdoc />
public virtual string GetName(string culture)
{
if (culture == null) return Name;
if (_names == null) return null;
return _names.TryGetValue(culture, out var name) ? name : null;
}
/// <inheritdoc />
public bool IsCultureAvailable(string culture)
=> !string.IsNullOrWhiteSpace(GetName(culture));
private void ClearName(string culture)
{
if (culture == null)
{
Name = null;
return;
}
if (_names == null) return;
_names.Remove(culture);
if (_names.Count == 0)
_names = null;
}
protected virtual void ClearNames()
{
_names = null;
OnPropertyChanged(Ps.Value.NamesSelector);
}
#endregion
#region Has, Get, Set, Publish Property Value #region Has, Get, Set, Publish Property Value
@@ -207,29 +216,29 @@ namespace Umbraco.Core.Models
=> Properties.Contains(propertyTypeAlias); => Properties.Contains(propertyTypeAlias);
/// <inheritdoc /> /// <inheritdoc />
public virtual object GetValue(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false) public virtual object GetValue(string propertyTypeAlias, string culture = null, string segment = null, bool published = false)
{ {
return Properties.TryGetValue(propertyTypeAlias, out var property) return Properties.TryGetValue(propertyTypeAlias, out var property)
? property.GetValue(languageId, segment, published) ? property.GetValue(culture, segment, published)
: null; : null;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual TValue GetValue<TValue>(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false) public virtual TValue GetValue<TValue>(string propertyTypeAlias, string culture = null, string segment = null, bool published = false)
{ {
if (!Properties.TryGetValue(propertyTypeAlias, out var property)) if (!Properties.TryGetValue(propertyTypeAlias, out var property))
return default; return default;
var convertAttempt = property.GetValue(languageId, segment, published).TryConvertTo<TValue>(); var convertAttempt = property.GetValue(culture, segment, published).TryConvertTo<TValue>();
return convertAttempt.Success ? convertAttempt.Result : default; return convertAttempt.Success ? convertAttempt.Result : default;
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual void SetValue(string propertyTypeAlias, object value, int? languageId = null, string segment = null) public virtual void SetValue(string propertyTypeAlias, object value, string culture = null, string segment = null)
{ {
if (Properties.Contains(propertyTypeAlias)) if (Properties.Contains(propertyTypeAlias))
{ {
Properties[propertyTypeAlias].SetValue(value, languageId, segment); Properties[propertyTypeAlias].SetValue(value, culture, segment);
return; return;
} }
@@ -238,7 +247,7 @@ namespace Umbraco.Core.Models
throw new InvalidOperationException($"No PropertyType exists with the supplied alias \"{propertyTypeAlias}\"."); throw new InvalidOperationException($"No PropertyType exists with the supplied alias \"{propertyTypeAlias}\".");
var property = propertyType.CreateProperty(); var property = propertyType.CreateProperty();
property.SetValue(value, languageId, segment); property.SetValue(value, culture, segment);
Properties.Add(property); Properties.Add(property);
} }
@@ -249,17 +258,17 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Sets the posted file value of a property. /// Sets the posted file value of a property.
/// </summary> /// </summary>
public virtual void SetValue(string propertyTypeAlias, HttpPostedFile value, int? languageId = null, string segment = null) public virtual void SetValue(string propertyTypeAlias, HttpPostedFile value, string culture = null, string segment = null)
{ {
ContentExtensions.SetValue(this, propertyTypeAlias, new HttpPostedFileWrapper(value), languageId, segment); ContentExtensions.SetValue(this, propertyTypeAlias, new HttpPostedFileWrapper(value), culture, segment);
} }
/// <summary> /// <summary>
/// Sets the posted file value of a property. /// Sets the posted file value of a property.
/// </summary> /// </summary>
public virtual void SetValue(string propertyTypeAlias, HttpPostedFileBase value, int? languageId = null, string segment = null) public virtual void SetValue(string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
{ {
ContentExtensions.SetValue(this, propertyTypeAlias, value, languageId, segment); ContentExtensions.SetValue(this, propertyTypeAlias, value, culture, segment);
} }
#endregion #endregion
@@ -271,14 +280,14 @@ namespace Umbraco.Core.Models
return Properties.Where(x => !x.IsAllValid()).ToArray(); return Properties.Where(x => !x.IsAllValid()).ToArray();
} }
public virtual Property[] Validate(int? languageId = null, string segment = null) public virtual Property[] Validate(string culture = null, string segment = null)
{ {
return Properties.Where(x => !x.IsValid(languageId, segment)).ToArray(); return Properties.Where(x => !x.IsValid(culture, segment)).ToArray();
} }
public virtual Property[] ValidateCulture(int? languageId = null) public virtual Property[] ValidateCulture(string culture = null)
{ {
return Properties.Where(x => !x.IsCultureValid(languageId)).ToArray(); return Properties.Where(x => !x.IsCultureValid(culture)).ToArray();
} }
#endregion #endregion

View File

@@ -159,20 +159,7 @@ namespace Umbraco.Core.Models
return Current.Services.MediaService.GetById(media.ParentId); return Current.Services.MediaService.GetById(media.ParentId);
} }
#endregion #endregion
#region Variants
/// <summary>
/// Returns true if the content has any property type that allows language variants
/// </summary>
public static bool HasPropertyTypeVaryingByCulture(this IContent content)
{
// fixme - what about CultureSegment? what about content.ContentType.Variations?
return content.PropertyTypes.Any(x => x.Variations == ContentVariation.CultureNeutral);
}
#endregion
/// <summary> /// <summary>
/// Removes characters that are not valide XML characters from all entity properties /// Removes characters that are not valide XML characters from all entity properties
/// of type string. See: http://stackoverflow.com/a/961504/5018 /// of type string. See: http://stackoverflow.com/a/961504/5018
@@ -284,7 +271,7 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Sets the posted file value of a property. /// Sets the posted file value of a property.
/// </summary> /// </summary>
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value, int? languageId = null, string segment = null) public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
{ {
// ensure we get the filename without the path in IE in intranet mode // ensure we get the filename without the path in IE in intranet mode
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie // http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
@@ -303,7 +290,7 @@ namespace Umbraco.Core.Models
if (string.IsNullOrWhiteSpace(filename)) return; if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why? filename = filename.ToLower(); // fixme - er... why?
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream, languageId, segment); MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream, culture, segment);
} }
/// <summary> /// <summary>
@@ -312,7 +299,7 @@ namespace Umbraco.Core.Models
/// <remarks>This really is for FileUpload fields only, and should be obsoleted. For anything else, /// <remarks>This really is for FileUpload fields only, and should be obsoleted. For anything else,
/// you need to store the file by yourself using Store and then figure out /// you need to store the file by yourself using Store and then figure out
/// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself.</remarks> /// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself.</remarks>
public static void SetValue(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, int? languageId = null, string segment = null) public static void SetValue(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
{ {
if (filename == null || filestream == null) return; if (filename == null || filestream == null) return;
@@ -321,7 +308,7 @@ namespace Umbraco.Core.Models
if (string.IsNullOrWhiteSpace(filename)) return; if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why? filename = filename.ToLower(); // fixme - er... why?
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, languageId, segment); MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
} }
/// <summary> /// <summary>

View File

@@ -204,10 +204,10 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Validates that a variation is valid for the content type. /// Validates that a variation is valid for the content type.
/// </summary> /// </summary>
public bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid) public bool ValidateVariation(string culture, string segment, bool throwIfInvalid)
{ {
ContentVariation variation; ContentVariation variation;
if (languageId.HasValue) if (culture != null)
{ {
variation = segment != null variation = segment != null
? ContentVariation.CultureSegment ? ContentVariation.CultureSegment
@@ -221,7 +221,7 @@ namespace Umbraco.Core.Models
{ {
variation = ContentVariation.InvariantNeutral; variation = ContentVariation.InvariantNeutral;
} }
if ((Variations & variation) == 0) if (!Variations.Has(variation))
{ {
if (throwIfInvalid) if (throwIfInvalid)
throw new NotSupportedException($"Variation {variation} is invalid for content type \"{Alias}\"."); throw new NotSupportedException($"Variation {variation} is invalid for content type \"{Alias}\".");

View File

@@ -146,13 +146,7 @@ namespace Umbraco.Core.Models
/// Gets or sets the file's virtual path (i.e. the file path relative to the root of the website) /// Gets or sets the file's virtual path (i.e. the file path relative to the root of the website)
/// </summary> /// </summary>
public string VirtualPath { get; set; } public string VirtualPath { get; set; }
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
public virtual bool IsValid()
{
return true;
}
// this exists so that class that manage name and alias differently, eg Template, // this exists so that class that manage name and alias differently, eg Template,
// can implement their own cloning - (though really, not sure it's even needed) // can implement their own cloning - (though really, not sure it's even needed)
protected virtual void DeepCloneNameAndAlias(File clone) protected virtual void DeepCloneNameAndAlias(File clone)

View File

@@ -59,7 +59,7 @@ namespace Umbraco.Core.Models
/// Gets the date and time the content was published. /// Gets the date and time the content was published.
/// </summary> /// </summary>
DateTime? PublishDate { get; } DateTime? PublishDate { get; }
/// <summary> /// <summary>
/// Gets or sets the date and time the content item should be published. /// Gets or sets the date and time the content item should be published.
/// </summary> /// </summary>
@@ -80,15 +80,6 @@ namespace Umbraco.Core.Models
/// </summary> /// </summary>
ContentStatus Status { get; } ContentStatus Status { get; }
/// <summary>
/// Gets a value indicating whether a given culture is available.
/// </summary>
/// <remarks>
/// <para>A culture becomes available whenever the content name for this culture is
/// non-null, and it becomes unavailable whenever the content name is null.</para>
/// </remarks>
bool IsCultureAvailable(int? languageId);
/// <summary> /// <summary>
/// Gets a value indicating whether a given culture is published. /// Gets a value indicating whether a given culture is published.
/// </summary> /// </summary>
@@ -97,17 +88,31 @@ namespace Umbraco.Core.Models
/// and the content published name for this culture is non-null. It becomes non-published /// and the content published name for this culture is non-null. It becomes non-published
/// whenever values for this culture are unpublished.</para> /// whenever values for this culture are unpublished.</para>
/// </remarks> /// </remarks>
bool IsCulturePublished(int? languageId); bool IsCulturePublished(string culture);
/// <summary>
/// Gets the date a culture was published.
/// </summary>
DateTime GetDateCulturePublished(string culture);
/// <summary>
/// Gets a value indicated whether a given culture is edited.
/// </summary>
/// <remarks>
/// <para>A culture is edited when it is not published, or when it is published but
/// it has changes.</para>
/// </remarks>
bool IsCultureEdited(string culture);
/// <summary> /// <summary>
/// Gets the name of the published version of the content for a given culture. /// Gets the name of the published version of the content for a given culture.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para>When editing the content, the name can change, but this will not until the content is published.</para> /// <para>When editing the content, the name can change, but this will not until the content is published.</para>
/// <para>When <paramref name="languageId"/> is <c>null</c>, gets the invariant /// <para>When <paramref name="culture"/> is <c>null</c>, gets the invariant
/// language, which is the value of the <see cref="PublishName"/> property.</para> /// language, which is the value of the <see cref="PublishName"/> property.</para>
/// </remarks> /// </remarks>
string GetPublishName(int? languageId); string GetPublishName(string culture);
/// <summary> /// <summary>
/// Gets the published names of the content. /// Gets the published names of the content.
@@ -116,7 +121,22 @@ namespace Umbraco.Core.Models
/// <para>Because a dictionary key cannot be <c>null</c> this cannot get the invariant /// <para>Because a dictionary key cannot be <c>null</c> this cannot get the invariant
/// name, which must be get via the <see cref="PublishName"/> property.</para> /// name, which must be get via the <see cref="PublishName"/> property.</para>
/// </remarks> /// </remarks>
IReadOnlyDictionary<int, string> PublishNames { get; } IReadOnlyDictionary<string, string> PublishNames { get; }
/// <summary>
/// Gets the available cultures.
/// </summary>
IEnumerable<string> AvailableCultures { get; }
/// <summary>
/// Gets the published cultures.
/// </summary>
IEnumerable<string> PublishedCultures { get; }
/// <summary>
/// Gets the edited cultures.
/// </summary>
IEnumerable<string> EditedCultures { get; }
// fixme - these two should move to some kind of service // fixme - these two should move to some kind of service
@@ -149,7 +169,8 @@ namespace Umbraco.Core.Models
/// <para>The document must then be published via the content service.</para> /// <para>The document must then be published via the content service.</para>
/// <para>Values are not published if they are not valie.</para> /// <para>Values are not published if they are not valie.</para>
/// </remarks> /// </remarks>
bool PublishAllValues(); //fixme return an Attempt with some error results if it doesn't work
bool TryPublishAllValues();
/// <summary> /// <summary>
/// Publishes values. /// Publishes values.
@@ -159,7 +180,8 @@ namespace Umbraco.Core.Models
/// <para>The document must then be published via the content service.</para> /// <para>The document must then be published via the content service.</para>
/// <para>Values are not published if they are not valid.</para> /// <para>Values are not published if they are not valid.</para>
/// </remarks> /// </remarks>
bool PublishValues(int? languageId = null, string segment = null); //fixme return an Attempt with some error results if it doesn't work
bool TryPublishValues(string culture = null, string segment = null);
/// <summary> /// <summary>
/// Publishes the culture/any values. /// Publishes the culture/any values.
@@ -169,7 +191,7 @@ namespace Umbraco.Core.Models
/// <para>The document must then be published via the content service.</para> /// <para>The document must then be published via the content service.</para>
/// <para>Values are not published if they are not valie.</para> /// <para>Values are not published if they are not valie.</para>
/// </remarks> /// </remarks>
bool PublishCultureValues(int? languageId = null); bool PublishCultureValues(string culture = null);
/// <summary> /// <summary>
/// Clears all published values. /// Clears all published values.
@@ -179,12 +201,12 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Clears published values. /// Clears published values.
/// </summary> /// </summary>
void ClearPublishedValues(int? languageId = null, string segment = null); void ClearPublishedValues(string culture = null, string segment = null);
/// <summary> /// <summary>
/// Clears the culture/any published values. /// Clears the culture/any published values.
/// </summary> /// </summary>
void ClearCulturePublishedValues(int? languageId = null); void ClearCulturePublishedValues(string culture = null);
/// <summary> /// <summary>
/// Copies values from another document. /// Copies values from another document.
@@ -194,11 +216,11 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Copies values from another document. /// Copies values from another document.
/// </summary> /// </summary>
void CopyValues(IContent other, int? languageId = null, string segment = null); void CopyValues(IContent other, string culture = null, string segment = null);
/// <summary> /// <summary>
/// Copies culture/any values from another document. /// Copies culture/any values from another document.
/// </summary> /// </summary>
void CopyCultureValues(IContent other, int? languageId = null); void CopyCultureValues(IContent other, string culture = null);
} }
} }

View File

@@ -31,19 +31,19 @@ namespace Umbraco.Core.Models
/// Sets the name of the content item for a specified language. /// Sets the name of the content item for a specified language.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para>When <paramref name="languageId"/> is <c>null</c>, sets the invariant /// <para>When <paramref name="culture"/> is <c>null</c>, sets the invariant
/// language, which sets the <see cref="TreeEntityBase.Name"/> property.</para> /// language, which sets the <see cref="TreeEntityBase.Name"/> property.</para>
/// </remarks> /// </remarks>
void SetName(int? languageId, string value); void SetName(string culture, string value);
/// <summary> /// <summary>
/// Gets the name of the content item for a specified language. /// Gets the name of the content item for a specified language.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para>When <paramref name="languageId"/> is <c>null</c>, gets the invariant /// <para>When <paramref name="culture"/> is <c>null</c>, gets the invariant
/// language, which is the value of the <see cref="TreeEntityBase.Name"/> property.</para> /// language, which is the value of the <see cref="TreeEntityBase.Name"/> property.</para>
/// </remarks> /// </remarks>
string GetName(int? languageId); string GetName(string culture);
/// <summary> /// <summary>
/// Gets or sets the names of the content item. /// Gets or sets the names of the content item.
@@ -51,9 +51,18 @@ namespace Umbraco.Core.Models
/// <remarks> /// <remarks>
/// <para>Because a dictionary key cannot be <c>null</c> this cannot get nor set the invariant /// <para>Because a dictionary key cannot be <c>null</c> this cannot get nor set the invariant
/// name, which must be get or set via the <see cref="TreeEntityBase.Name"/> property.</para> /// name, which must be get or set via the <see cref="TreeEntityBase.Name"/> property.</para>
/// </remarks> /// </remarks>
IReadOnlyDictionary<int, string> Names { get; set; } IReadOnlyDictionary<string, string> Names { get; set; }
/// <summary>
/// Gets a value indicating whether a given culture is available.
/// </summary>
/// <remarks>
/// <para>A culture becomes available whenever the content name for this culture is
/// non-null, and it becomes unavailable whenever the content name is null.</para>
/// </remarks>
bool IsCultureAvailable(string culture);
/// <summary> /// <summary>
/// List of properties, which make up all the data available for this Content object /// List of properties, which make up all the data available for this Content object
/// </summary> /// </summary>
@@ -82,17 +91,17 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Gets the value of a Property /// Gets the value of a Property
/// </summary> /// </summary>
object GetValue(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false); object GetValue(string propertyTypeAlias, string culture = null, string segment = null, bool published = false);
/// <summary> /// <summary>
/// Gets the typed value of a Property /// Gets the typed value of a Property
/// </summary> /// </summary>
TValue GetValue<TValue>(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false); TValue GetValue<TValue>(string propertyTypeAlias, string culture = null, string segment = null, bool published = false);
/// <summary> /// <summary>
/// Sets the (edited) value of a Property /// Sets the (edited) value of a Property
/// </summary> /// </summary>
void SetValue(string propertyTypeAlias, object value, int? languageId = null, string segment = null); void SetValue(string propertyTypeAlias, object value, string culture = null, string segment = null);
/// <summary> /// <summary>
/// Gets a value indicating whether the content and all its properties values are valid. /// Gets a value indicating whether the content and all its properties values are valid.
@@ -102,11 +111,11 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Gets a value indicating whether the content and its properties values are valid. /// Gets a value indicating whether the content and its properties values are valid.
/// </summary> /// </summary>
Property[] Validate(int? languageId = null, string segment = null); Property[] Validate(string culture = null, string segment = null);
/// <summary> /// <summary>
/// Gets a value indicating whether the content and its culture/any properties values are valid. /// Gets a value indicating whether the content and its culture/any properties values are valid.
/// </summary> /// </summary>
Property[] ValidateCulture(int? languageId = null); Property[] ValidateCulture(string culture = null);
} }
} }

View File

@@ -51,7 +51,7 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Validates that a variation is valid for the content type. /// Validates that a variation is valid for the content type.
/// </summary> /// </summary>
bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid); bool ValidateVariation(string culture, string segment, bool throwIfInvalid);
/// <summary> /// <summary>
/// Gets or Sets a list of integer Ids of the ContentTypes allowed under the ContentType /// Gets or Sets a list of integer Ids of the ContentTypes allowed under the ContentType

View File

@@ -43,8 +43,6 @@ namespace Umbraco.Core.Models
/// Gets or sets the file's virtual path (i.e. the file path relative to the root of the website) /// Gets or sets the file's virtual path (i.e. the file path relative to the root of the website)
/// </summary> /// </summary>
string VirtualPath { get; set; } string VirtualPath { get; set; }
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
bool IsValid();
} }
} }

View File

@@ -51,35 +51,19 @@ namespace Umbraco.Core.Models
/// </summary> /// </summary>
[DataMember] [DataMember]
bool DontRender { get; set; } bool DontRender { get; set; }
/// <summary> /// <summary>
/// Gets or sets the path to user control or the Control Type to render /// Gets or set the path to the macro source to render
/// </summary> /// </summary>
[DataMember] [DataMember]
string ControlType { get; set; } string MacroSource { get; set; }
/// <summary> /// <summary>
/// Gets or sets the name of the assembly, which should be used by the Macro /// Gets or set the macro type
/// </summary> /// </summary>
/// <remarks>Will usually only be filled if the ScriptFile is a Usercontrol</remarks>
[DataMember] [DataMember]
[Obsolete("This is no longer used, we should remove it in v8, CustomControl macros are gone")] MacroTypes MacroType { get; set; }
string ControlAssembly { get; set; }
/// <summary>
/// Gets or set the path to the Python file in use
/// </summary>
/// <remarks>Optional: Can only be one of three Script, Python or Xslt</remarks>
[DataMember]
string ScriptPath { get; set; }
/// <summary>
/// Gets or sets the path to the Xslt file in use
/// </summary>
/// <remarks>Optional: Can only be one of three Script, Python or Xslt</remarks>
[DataMember]
string XsltPath { get; set; }
/// <summary> /// <summary>
/// Gets or sets a list of Macro Properties /// Gets or sets a list of Macro Properties
/// </summary> /// </summary>

View File

@@ -1,7 +0,0 @@
namespace Umbraco.Core.Models
{
public interface IXsltFile : IFile
{
}
}

View File

@@ -34,14 +34,11 @@ namespace Umbraco.Core.Models
/// <param name="cacheDuration"></param> /// <param name="cacheDuration"></param>
/// <param name="alias"></param> /// <param name="alias"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="controlType"></param>
/// <param name="controlAssembly"></param>
/// <param name="xsltPath"></param>
/// <param name="cacheByPage"></param> /// <param name="cacheByPage"></param>
/// <param name="cacheByMember"></param> /// <param name="cacheByMember"></param>
/// <param name="dontRender"></param> /// <param name="dontRender"></param>
/// <param name="scriptPath"></param> /// <param name="macroSource"></param>
public Macro(int id, Guid key, bool useInEditor, int cacheDuration, string @alias, string name, string controlType, string controlAssembly, string xsltPath, bool cacheByPage, bool cacheByMember, bool dontRender, string scriptPath) public Macro(int id, Guid key, bool useInEditor, int cacheDuration, string @alias, string name, bool cacheByPage, bool cacheByMember, bool dontRender, string macroSource, MacroTypes macroType)
: this() : this()
{ {
Id = id; Id = id;
@@ -50,13 +47,11 @@ namespace Umbraco.Core.Models
CacheDuration = cacheDuration; CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias); Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name; Name = name;
ControlType = controlType;
ControlAssembly = controlAssembly;
XsltPath = xsltPath;
CacheByPage = cacheByPage; CacheByPage = cacheByPage;
CacheByMember = cacheByMember; CacheByMember = cacheByMember;
DontRender = dontRender; DontRender = dontRender;
ScriptPath = scriptPath; MacroSource = macroSource;
MacroType = macroType;
} }
/// <summary> /// <summary>
@@ -66,18 +61,13 @@ namespace Umbraco.Core.Models
/// <param name="cacheDuration"></param> /// <param name="cacheDuration"></param>
/// <param name="alias"></param> /// <param name="alias"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="controlType"></param>
/// <param name="controlAssembly"></param>
/// <param name="xsltPath"></param>
/// <param name="cacheByPage"></param> /// <param name="cacheByPage"></param>
/// <param name="cacheByMember"></param> /// <param name="cacheByMember"></param>
/// <param name="dontRender"></param> /// <param name="dontRender"></param>
/// <param name="scriptPath"></param> /// <param name="macroSource"></param>
public Macro(string @alias, string name, public Macro(string @alias, string name,
string controlType = "", string macroSource,
string controlAssembly = "", MacroTypes macroType,
string xsltPath = "",
string scriptPath = "",
bool cacheByPage = false, bool cacheByPage = false,
bool cacheByMember = false, bool cacheByMember = false,
bool dontRender = true, bool dontRender = true,
@@ -89,13 +79,11 @@ namespace Umbraco.Core.Models
CacheDuration = cacheDuration; CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias); Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name; Name = name;
ControlType = controlType;
ControlAssembly = controlAssembly;
XsltPath = xsltPath;
CacheByPage = cacheByPage; CacheByPage = cacheByPage;
CacheByMember = cacheByMember; CacheByMember = cacheByMember;
DontRender = dontRender; DontRender = dontRender;
ScriptPath = scriptPath; MacroSource = macroSource;
MacroType = macroType;
} }
private string _alias; private string _alias;
@@ -105,10 +93,8 @@ namespace Umbraco.Core.Models
private bool _cacheByPage; private bool _cacheByPage;
private bool _cacheByMember; private bool _cacheByMember;
private bool _dontRender; private bool _dontRender;
private string _scriptFile; private string _macroSource;
private string _scriptAssembly; private MacroTypes _macroType = MacroTypes.Unknown;
private string _scriptPath;
private string _xslt;
private MacroPropertyCollection _properties; private MacroPropertyCollection _properties;
private List<string> _addedProperties; private List<string> _addedProperties;
private List<string> _removedProperties; private List<string> _removedProperties;
@@ -124,10 +110,8 @@ namespace Umbraco.Core.Models
public readonly PropertyInfo CacheByPageSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByPage); public readonly PropertyInfo CacheByPageSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByPage);
public readonly PropertyInfo CacheByMemberSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByMember); public readonly PropertyInfo CacheByMemberSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByMember);
public readonly PropertyInfo DontRenderSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.DontRender); public readonly PropertyInfo DontRenderSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.DontRender);
public readonly PropertyInfo ControlPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlType); public readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.MacroSource);
public readonly PropertyInfo ControlAssemblySelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlAssembly); public readonly PropertyInfo MacroTypeSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroTypes>(x => x.MacroType);
public readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ScriptPath);
public readonly PropertyInfo XsltPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.XsltPath);
public readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroPropertyCollection>(x => x.Properties); public readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroPropertyCollection>(x => x.Properties);
} }
@@ -272,46 +256,23 @@ namespace Umbraco.Core.Models
} }
/// <summary> /// <summary>
/// Gets or sets the path to user control or the Control Type to render /// Gets or set the path to the Partial View to render
/// </summary> /// </summary>
[DataMember] [DataMember]
public string ControlType public string MacroSource
{ {
get { return _scriptFile; } get { return _macroSource; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptFile, Ps.Value.ControlPathSelector); } set { SetPropertyValueAndDetectChanges(value, ref _macroSource, Ps.Value.ScriptPathSelector); }
} }
/// <summary> /// <summary>
/// Gets or sets the name of the assembly, which should be used by the Macro /// Gets or set the path to the Partial View to render
/// </summary> /// </summary>
/// <remarks>Will usually only be filled if the ControlType is a Usercontrol</remarks>
[DataMember] [DataMember]
public string ControlAssembly public MacroTypes MacroType
{ {
get { return _scriptAssembly; } get { return _macroType; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptAssembly, Ps.Value.ControlAssemblySelector); } set { SetPropertyValueAndDetectChanges(value, ref _macroType, Ps.Value.MacroTypeSelector); }
}
/// <summary>
/// Gets or set the path to the Python file in use
/// </summary>
/// <remarks>Optional: Can only be one of three Script, Python or Xslt</remarks>
[DataMember]
public string ScriptPath
{
get { return _scriptPath; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptPath, Ps.Value.ScriptPathSelector); }
}
/// <summary>
/// Gets or sets the path to the Xslt file in use
/// </summary>
/// <remarks>Optional: Can only be one of three Script, Python or Xslt</remarks>
[DataMember]
public string XsltPath
{
get { return _xslt; }
set { SetPropertyValueAndDetectChanges(value, ref _xslt, Ps.Value.XsltPathSelector); }
} }
/// <summary> /// <summary>

View File

@@ -10,15 +10,11 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)] [DataContract(IsReference = true)]
public enum MacroTypes public enum MacroTypes
{ {
[EnumMember]
Xslt = 1,
[EnumMember] [EnumMember]
UserControl = 3, UserControl = 3,
[EnumMember] [EnumMember]
Unknown = 4, Unknown = 4,
[EnumMember] [EnumMember]
Script = 6,
[EnumMember]
PartialView = 7 PartialView = 7
} }
} }

View File

@@ -48,7 +48,7 @@ namespace Umbraco.Core.Models
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset /// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IMediaType DeepCloneWithResetIdentities(string alias) public new IMediaType DeepCloneWithResetIdentities(string alias)
{ {
var clone = (MediaType)DeepClone(); var clone = (MediaType)DeepClone();
clone.Alias = alias; clone.Alias = alias;

View File

@@ -18,11 +18,7 @@ namespace Umbraco.Core.Models.Membership
int[] StartContentIds { get; set; } int[] StartContentIds { get; set; }
int[] StartMediaIds { get; set; } int[] StartMediaIds { get; set; }
string Language { get; set; } string Language { get; set; }
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUserType UserType { get; set; }
DateTime? EmailConfirmedDate { get; set; } DateTime? EmailConfirmedDate { get; set; }
DateTime? InvitedDate { get; set; } DateTime? InvitedDate { get; set; }
@@ -37,14 +33,6 @@ namespace Umbraco.Core.Models.Membership
IEnumerable<string> AllowedSections { get; } IEnumerable<string> AllowedSections { get; }
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
void RemoveAllowedSection(string sectionAlias);
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
void AddAllowedSection(string sectionAlias);
/// <summary> /// <summary>
/// Exposes the basic profile data /// Exposes the basic profile data
/// </summary> /// </summary>
@@ -65,4 +53,4 @@ namespace Umbraco.Core.Models.Membership
/// </summary> /// </summary>
string TourData { get; set; } string TourData { get; set; }
} }
} }

View File

@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
{
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IUserType : IEntity
{
string Alias { get; set; }
string Name { get; set; }
IEnumerable<string> Permissions { get; set; }
}
}

View File

@@ -284,162 +284,6 @@ namespace Umbraco.Core.Models.Membership
get { return _allowedSections ?? (_allowedSections = new List<string>(_userGroups.SelectMany(x => x.AllowedSections).Distinct())); } get { return _allowedSections ?? (_allowedSections = new List<string>(_userGroups.SelectMany(x => x.AllowedSections).Distinct())); }
} }
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUserType IUser.UserType
{
get
{
//the best we can do here is to return the user's first user group as a IUserType object
//but we should attempt to return any group that is the built in ones first
var groups = Groups.ToArray();
if (groups.Length == 0)
{
//In backwards compatibility land, a user type cannot be null! so we need to return a fake one.
return new UserType
{
Alias = "temp",
Id = int.MinValue,
Key = Guid.Empty,
CreateDate = default(DateTime),
DeleteDate = null,
Name = "Temp",
Permissions = new List<string>(),
UpdateDate = default(DateTime)
};
}
var builtIns = new[] { Constants.Security.AdminGroupAlias, "writer", "editor", "translator" };
var foundBuiltIn = groups.FirstOrDefault(x => builtIns.Contains(x.Alias));
IUserGroup realGroup;
if (foundBuiltIn != null)
{
//if the group isn't IUserGroup we'll need to look it up
realGroup = foundBuiltIn as IUserGroup ?? Current.Services.UserService.GetUserGroupById(foundBuiltIn.Id);
//return a mapped version of the group
return new UserType
{
Alias = realGroup.Alias,
Id = realGroup.Id,
Key = realGroup.Key,
CreateDate = realGroup.CreateDate,
DeleteDate = realGroup.DeleteDate,
Name = realGroup.Name,
Permissions = realGroup.Permissions,
UpdateDate = realGroup.UpdateDate
};
}
//otherwise return the first
//if the group isn't IUserGroup we'll need to look it up
realGroup = groups[0] as IUserGroup ?? Current.Services.UserService.GetUserGroupById(groups[0].Id);
//return a mapped version of the group
return new UserType
{
Alias = realGroup.Alias,
Id = realGroup.Id,
Key = realGroup.Key,
CreateDate = realGroup.CreateDate,
DeleteDate = realGroup.DeleteDate,
Name = realGroup.Name,
Permissions = realGroup.Permissions,
UpdateDate = realGroup.UpdateDate
};
}
set
{
//if old APIs are still using this lets first check if the user is part of the user group with the alias specified
if (Groups.Any(x => x.Alias == value.Alias))
return;
//the only other option we have here is to lookup the group (and we'll need to use singletons here :( )
var found = Current.Services.UserService.GetUserGroupByAlias(value.Alias);
if (found == null)
throw new InvalidOperationException("No user group was found with the alias " + value.Alias + ", this API (IUser.UserType) is obsolete, use user groups instead");
//if it's found, all we can do is add it, we can't really replace them
AddGroup(found.ToReadOnlyGroup());
}
}
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
void IUser.RemoveAllowedSection(string sectionAlias)
{
//don't do anything if they aren't allowed it already
if (AllowedSections.Contains(sectionAlias) == false)
return;
var groups = Groups.ToArray();
//our only option here is to check if a custom group is created for this user, if so we can remove it from that group, otherwise we'll throw
//now we'll check if the user has a special 1:1 user group created for itself. This will occur if this method is used and also during an upgrade.
//this comes in the alias form of userName + 'Group'
var customUserGroup = groups.FirstOrDefault(x => x.Alias == (Username + "Group"));
if (customUserGroup != null)
{
//if the group isn't IUserGroup we'll need to look it up
var realGroup = customUserGroup as IUserGroup ?? Current.Services.UserService.GetUserGroupById(customUserGroup.Id);
realGroup.RemoveAllowedSection(sectionAlias);
//now we need to flag this for saving (hack!)
GroupsToSave.Add(realGroup);
}
else
{
throw new InvalidOperationException("Cannot remove the allowed section using this obsolete API. Modify the user's groups instead");
}
}
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
void IUser.AddAllowedSection(string sectionAlias)
{
//don't do anything if they are allowed it already
if (AllowedSections.Contains(sectionAlias))
return;
//This is here for backwards compat only.
//First we'll check if the user is part of the 'admin' group. If so then we can ensure that the admin group has this section available to it.
//otherwise, the only thing we can do is create a custom user group for this user and add this section.
//We are checking for admin here because if the user is an admin and an allowed section is being added, then it's assumed it's to be added
//for the whole admin group (i.e. Forms installer does this for admins)
var groups = Groups.ToArray();
var admin = groups.FirstOrDefault(x => x.Alias == Constants.Security.AdminGroupAlias);
if (admin != null)
{
//if the group isn't IUserGroup we'll need to look it up
var realGroup = admin as IUserGroup ?? Current.Services.UserService.GetUserGroupById(admin.Id);
realGroup.AddAllowedSection(sectionAlias);
//now we need to flag this for saving (hack!)
GroupsToSave.Add(realGroup);
}
else
{
//now we'll check if the user has a special 1:1 user group created for itself. This will occur if this method is used and also during an upgrade.
//this comes in the alias form of userName + 'Group'
var customUserGroup = groups.FirstOrDefault(x => x.Alias == (Username + "Group"));
if (customUserGroup != null)
{
//if the group isn't IUserGroup we'll need to look it up
var realGroup = customUserGroup as IUserGroup ?? Current.Services.UserService.GetUserGroupById(customUserGroup.Id);
realGroup.AddAllowedSection(sectionAlias);
//now we need to flag this for saving (hack!)
GroupsToSave.Add(realGroup);
}
//ok, so the user doesn't have a 1:1 group, we'll need to flag it for creation
var newUserGroup = new UserGroup
{
Alias = Username + "Group",
Name = "Group for " + Username
};
newUserGroup.AddAllowedSection(sectionAlias);
//add this user to this new group
AddGroup(newUserGroup);
GroupsToSave.Add(newUserGroup);
}
}
/// <summary> /// <summary>
/// This used purely for hacking backwards compatibility into this class for &lt; 7.7 compat /// This used purely for hacking backwards compatibility into this class for &lt; 7.7 compat
/// </summary> /// </summary>

View File

@@ -1,78 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models.Membership
{
[Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
[Serializable]
[DataContract(IsReference = true)]
internal class UserType : EntityBase, IUserType
{
private string _alias;
private string _name;
private IEnumerable<string> _permissions;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<UserType, string>(x => x.Name);
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<UserType, string>(x => x.Alias);
public readonly PropertyInfo PermissionsSelector = ExpressionHelper.GetPropertyInfo<UserType, IEnumerable<string>>(x => x.Permissions);
}
public UserType(string name, string alias)
{
Name = name;
Alias = alias;
}
public UserType()
{
}
[DataMember]
public string Alias
{
get { return _alias; }
set
{
SetPropertyValueAndDetectChanges(
value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase),
ref _alias,
Ps.Value.AliasSelector);
}
}
[DataMember]
public string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
}
/// <summary>
/// The set of default permissions for the user type
/// </summary>
/// <remarks>
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
/// </remarks>
[DataMember]
public IEnumerable<string> Permissions
{
get { return _permissions; }
set
{
SetPropertyValueAndDetectChanges(value, ref _permissions, Ps.Value.PermissionsSelector,
//Custom comparer for enumerable
new DelegateEqualityComparer<IEnumerable<string>>(
(enum1, enum2) => enum1.UnsortedSequenceEqual(enum2),
enum1 => enum1.GetHashCode()));
}
}
}
}

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models
{ {
private List<PropertyValue> _values = new List<PropertyValue>(); private List<PropertyValue> _values = new List<PropertyValue>();
private PropertyValue _pvalue; private PropertyValue _pvalue;
private Dictionary<CompositeIntStringKey, PropertyValue> _vvalues; private Dictionary<CompositeStringStringKey, PropertyValue> _vvalues;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>(); private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
@@ -38,9 +38,14 @@ namespace Umbraco.Core.Models
public class PropertyValue public class PropertyValue
{ {
private string _culture;
private string _segment; private string _segment;
public int? LanguageId { get; internal set; } public string Culture
{
get => _culture;
internal set => _culture = value?.ToLowerInvariant();
}
public string Segment public string Segment
{ {
get => _segment; get => _segment;
@@ -50,7 +55,7 @@ namespace Umbraco.Core.Models
public object PublishedValue { get; internal set; } public object PublishedValue { get; internal set; }
public PropertyValue Clone() public PropertyValue Clone()
=> new PropertyValue { LanguageId = LanguageId, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue }; => new PropertyValue { _culture = _culture, _segment = _segment, PublishedValue = PublishedValue, EditedValue = EditedValue };
} }
// ReSharper disable once ClassNeverInstantiated.Local // ReSharper disable once ClassNeverInstantiated.Local
@@ -96,10 +101,10 @@ namespace Umbraco.Core.Models
{ {
// make sure we filter out invalid variations // make sure we filter out invalid variations
// make sure we leave _vvalues null if possible // make sure we leave _vvalues null if possible
_values = value.Where(x => PropertyType.ValidateVariation(x.LanguageId, x.Segment, false)).ToList(); _values = value.Where(x => PropertyType.ValidateVariation(x.Culture, x.Segment, false)).ToList();
_pvalue = _values.FirstOrDefault(x => !x.LanguageId.HasValue && x.Segment == null); _pvalue = _values.FirstOrDefault(x => x.Culture == null && x.Segment == null);
_vvalues = _values.Count > (_pvalue == null ? 0 : 1) _vvalues = _values.Count > (_pvalue == null ? 0 : 1)
? _values.Where(x => x != _pvalue).ToDictionary(x => new CompositeIntStringKey(x.LanguageId, x.Segment), x => x) ? _values.Where(x => x != _pvalue).ToDictionary(x => new CompositeStringStringKey(x.Culture, x.Segment), x => x)
: null; : null;
} }
} }
@@ -128,12 +133,12 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Gets the value. /// Gets the value.
/// </summary> /// </summary>
public object GetValue(int? languageId = null, string segment = null, bool published = false) public object GetValue(string culture = null, string segment = null, bool published = false)
{ {
if (!PropertyType.ValidateVariation(languageId, segment, false)) return null; if (!PropertyType.ValidateVariation(culture, segment, false)) return null;
if (!languageId.HasValue && segment == null) return GetPropertyValue(_pvalue, published); if (culture == null && segment == null) return GetPropertyValue(_pvalue, published);
if (_vvalues == null) return null; if (_vvalues == null) return null;
return _vvalues.TryGetValue(new CompositeIntStringKey(languageId, segment), out var pvalue) return _vvalues.TryGetValue(new CompositeStringStringKey(culture, segment), out var pvalue)
? GetPropertyValue(pvalue, published) ? GetPropertyValue(pvalue, published)
: null; : null;
} }
@@ -159,7 +164,7 @@ namespace Umbraco.Core.Models
if (_vvalues != null) if (_vvalues != null)
{ {
var pvalues = _vvalues var pvalues = _vvalues
.Where(x => PropertyType.ValidateVariation(x.Value.LanguageId, x.Value.Segment, false)) .Where(x => PropertyType.ValidateVariation(x.Value.Culture, x.Value.Segment, false))
.Select(x => x.Value); .Select(x => x.Value);
foreach (var pvalue in pvalues) foreach (var pvalue in pvalues)
PublishPropertyValue(pvalue); PublishPropertyValue(pvalue);
@@ -168,29 +173,29 @@ namespace Umbraco.Core.Models
// internal - must be invoked by the content item // internal - must be invoked by the content item
// does *not* validate the value - content item must validate first // does *not* validate the value - content item must validate first
internal void PublishValue(int? languageId = null, string segment = null) internal void PublishValue(string culture = null, string segment = null)
{ {
PropertyType.ValidateVariation(languageId, segment, true); PropertyType.ValidateVariation(culture, segment, true);
(var pvalue, _) = GetPValue(languageId, segment, false); (var pvalue, _) = GetPValue(culture, segment, false);
if (pvalue == null) return; if (pvalue == null) return;
PublishPropertyValue(pvalue); PublishPropertyValue(pvalue);
} }
// internal - must be invoked by the content item // internal - must be invoked by the content item
// does *not* validate the value - content item must validate first // does *not* validate the value - content item must validate first
internal void PublishCultureValues(int? languageId = null) internal void PublishCultureValues(string culture = null)
{ {
// if invariant and invariant-neutral is supported, publish invariant-neutral // if invariant and invariant-neutral is supported, publish invariant-neutral
if (!languageId.HasValue && PropertyType.ValidateVariation(null, null, false)) if (culture == null && PropertyType.ValidateVariation(null, null, false))
PublishPropertyValue(_pvalue); PublishPropertyValue(_pvalue);
// publish everything not invariant-neutral that matches the culture and is supported // publish everything not invariant-neutral that matches the culture and is supported
if (_vvalues != null) if (_vvalues != null)
{ {
var pvalues = _vvalues var pvalues = _vvalues
.Where(x => x.Value.LanguageId == languageId) .Where(x => x.Value.Culture.InvariantEquals(culture))
.Where(x => PropertyType.ValidateVariation(languageId, x.Value.Segment, false)) .Where(x => PropertyType.ValidateVariation(culture, x.Value.Segment, false))
.Select(x => x.Value); .Select(x => x.Value);
foreach (var pvalue in pvalues) foreach (var pvalue in pvalues)
PublishPropertyValue(pvalue); PublishPropertyValue(pvalue);
@@ -206,7 +211,7 @@ namespace Umbraco.Core.Models
if (_vvalues != null) if (_vvalues != null)
{ {
var pvalues = _vvalues var pvalues = _vvalues
.Where(x => PropertyType.ValidateVariation(x.Value.LanguageId, x.Value.Segment, false)) .Where(x => PropertyType.ValidateVariation(x.Value.Culture, x.Value.Segment, false))
.Select(x => x.Value); .Select(x => x.Value);
foreach (var pvalue in pvalues) foreach (var pvalue in pvalues)
ClearPublishedPropertyValue(pvalue); ClearPublishedPropertyValue(pvalue);
@@ -214,25 +219,25 @@ namespace Umbraco.Core.Models
} }
// internal - must be invoked by the content item // internal - must be invoked by the content item
internal void ClearPublishedValue(int? languageId = null, string segment = null) internal void ClearPublishedValue(string culture = null, string segment = null)
{ {
PropertyType.ValidateVariation(languageId, segment, true); PropertyType.ValidateVariation(culture, segment, true);
(var pvalue, _) = GetPValue(languageId, segment, false); (var pvalue, _) = GetPValue(culture, segment, false);
if (pvalue == null) return; if (pvalue == null) return;
ClearPublishedPropertyValue(pvalue); ClearPublishedPropertyValue(pvalue);
} }
// internal - must be invoked by the content item // internal - must be invoked by the content item
internal void ClearPublishedCultureValues(int? languageId = null) internal void ClearPublishedCultureValues(string culture = null)
{ {
if (!languageId.HasValue && PropertyType.ValidateVariation(null, null, false)) if (culture == null && PropertyType.ValidateVariation(null, null, false))
ClearPublishedPropertyValue(_pvalue); ClearPublishedPropertyValue(_pvalue);
if (_vvalues != null) if (_vvalues != null)
{ {
var pvalues = _vvalues var pvalues = _vvalues
.Where(x => x.Value.LanguageId == languageId) .Where(x => x.Value.Culture.InvariantEquals(culture))
.Where(x => PropertyType.ValidateVariation(languageId, x.Value.Segment, false)) .Where(x => PropertyType.ValidateVariation(culture, x.Value.Segment, false))
.Select(x => x.Value); .Select(x => x.Value);
foreach (var pvalue in pvalues) foreach (var pvalue in pvalues)
ClearPublishedPropertyValue(pvalue); ClearPublishedPropertyValue(pvalue);
@@ -264,10 +269,10 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Sets a value. /// Sets a value.
/// </summary> /// </summary>
public void SetValue(object value, int? languageId = null, string segment = null) public void SetValue(object value, string culture = null, string segment = null)
{ {
PropertyType.ValidateVariation(languageId, segment, true); PropertyType.ValidateVariation(culture, segment, true);
(var pvalue, var change) = GetPValue(languageId, segment, true); (var pvalue, var change) = GetPValue(culture, segment, true);
var origValue = pvalue.EditedValue; var origValue = pvalue.EditedValue;
var setValue = PropertyType.ConvertAssignedValue(value); var setValue = PropertyType.ConvertAssignedValue(value);
@@ -278,9 +283,9 @@ namespace Umbraco.Core.Models
} }
// bypasses all changes detection and is the *only* way to set the published value // bypasses all changes detection and is the *only* way to set the published value
internal void FactorySetValue(int? languageId, string segment, bool published, object value) internal void FactorySetValue(string culture, string segment, bool published, object value)
{ {
(var pvalue, _) = GetPValue(languageId, segment, true); (var pvalue, _) = GetPValue(culture, segment, true);
if (published && PropertyType.IsPublishing) if (published && PropertyType.IsPublishing)
pvalue.PublishedValue = value; pvalue.PublishedValue = value;
@@ -301,24 +306,24 @@ namespace Umbraco.Core.Models
return (_pvalue, change); return (_pvalue, change);
} }
private (PropertyValue, bool) GetPValue(int? languageId, string segment, bool create) private (PropertyValue, bool) GetPValue(string culture, string segment, bool create)
{ {
if (!languageId.HasValue && segment == null) if (culture == null && segment == null)
return GetPValue(create); return GetPValue(create);
var change = false; var change = false;
if (_vvalues == null) if (_vvalues == null)
{ {
if (!create) return (null, false); if (!create) return (null, false);
_vvalues = new Dictionary<CompositeIntStringKey, PropertyValue>(); _vvalues = new Dictionary<CompositeStringStringKey, PropertyValue>();
change = true; change = true;
} }
var k = new CompositeIntStringKey(languageId, segment); var k = new CompositeStringStringKey(culture, segment);
if (!_vvalues.TryGetValue(k, out var pvalue)) if (!_vvalues.TryGetValue(k, out var pvalue))
{ {
if (!create) return (null, false); if (!create) return (null, false);
pvalue = _vvalues[k] = new PropertyValue(); pvalue = _vvalues[k] = new PropertyValue();
pvalue.LanguageId = languageId; pvalue.Culture = culture;
pvalue.Segment = segment; pvalue.Segment = segment;
_values.Add(pvalue); _values.Add(pvalue);
change = true; change = true;
@@ -343,7 +348,7 @@ namespace Umbraco.Core.Models
if (_vvalues == null) return true; if (_vvalues == null) return true;
var pvalues = _vvalues var pvalues = _vvalues
.Where(x => PropertyType.ValidateVariation(x.Value.LanguageId, x.Value.Segment, false)) .Where(x => PropertyType.ValidateVariation(x.Value.Culture, x.Value.Segment, false))
.Select(x => x.Value) .Select(x => x.Value)
.ToArray(); .ToArray();
@@ -354,11 +359,11 @@ namespace Umbraco.Core.Models
/// Gets a value indicating whether the culture/any values are valid. /// Gets a value indicating whether the culture/any values are valid.
/// </summary> /// </summary>
/// <remarks>An invalid value can be saved, but only valid values can be published.</remarks> /// <remarks>An invalid value can be saved, but only valid values can be published.</remarks>
public bool IsCultureValid(int? languageId) public bool IsCultureValid(string culture)
{ {
// culture-neutral is supported, validate culture-neutral // culture-neutral is supported, validate culture-neutral
// includes mandatory validation // includes mandatory validation
if (PropertyType.ValidateVariation(languageId, null, false) && !IsValidValue(GetValue(languageId))) if (PropertyType.ValidateVariation(culture, null, false) && !IsValidValue(GetValue(culture)))
return false; return false;
// either culture-neutral is not supported, or it is valid // either culture-neutral is not supported, or it is valid
@@ -368,8 +373,8 @@ namespace Umbraco.Core.Models
if (_vvalues == null) return true; if (_vvalues == null) return true;
var pvalues = _vvalues var pvalues = _vvalues
.Where(x => x.Value.LanguageId == languageId) .Where(x => x.Value.Culture.InvariantEquals(culture))
.Where(x => PropertyType.ValidateVariation(languageId, x.Value.Segment, false)) .Where(x => PropertyType.ValidateVariation(culture, x.Value.Segment, false))
.Select(x => x.Value) .Select(x => x.Value)
.ToArray(); .ToArray();
@@ -380,10 +385,10 @@ namespace Umbraco.Core.Models
/// Gets a value indicating whether the value is valid. /// Gets a value indicating whether the value is valid.
/// </summary> /// </summary>
/// <remarks>An invalid value can be saved, but only valid values can be published.</remarks> /// <remarks>An invalid value can be saved, but only valid values can be published.</remarks>
public bool IsValid(int? languageId = null, string segment = null) public bool IsValid(string culture = null, string segment = null)
{ {
// single value -> validates mandatory // single value -> validates mandatory
return IsValidValue(GetValue(languageId, segment)); return IsValidValue(GetValue(culture, segment));
} }
/// <summary> /// <summary>

View File

@@ -67,8 +67,10 @@ namespace Umbraco.Core.Models
internal new void Add(PropertyGroup item) internal new void Add(PropertyGroup item)
{ {
using (new WriteLock(_addLocker)) try
{ {
_addLocker.EnterWriteLock();
//Note this is done to ensure existig groups can be renamed //Note this is done to ensure existig groups can be renamed
if (item.HasIdentity && item.Id > 0) if (item.HasIdentity && item.Id > 0)
{ {
@@ -102,6 +104,11 @@ namespace Umbraco.Core.Models
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
} }
finally
{
if (_addLocker.IsWriteLockHeld)
_addLocker.ExitWriteLock();
}
} }
/// <summary> /// <summary>

View File

@@ -226,10 +226,10 @@ namespace Umbraco.Core.Models
/// <summary> /// <summary>
/// Validates that a variation is valid for the property type. /// Validates that a variation is valid for the property type.
/// </summary> /// </summary>
public bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid) public bool ValidateVariation(string culture, string segment, bool throwIfInvalid)
{ {
ContentVariation variation; ContentVariation variation;
if (languageId.HasValue) if (culture != null)
{ {
variation = segment != null variation = segment != null
? ContentVariation.CultureSegment ? ContentVariation.CultureSegment
@@ -243,7 +243,7 @@ namespace Umbraco.Core.Models
{ {
variation = ContentVariation.InvariantNeutral; variation = ContentVariation.InvariantNeutral;
} }
if ((Variations & variation) == 0) if (!Variations.Has(variation))
{ {
if (throwIfInvalid) if (throwIfInvalid)
throw new NotSupportedException($"Variation {variation} is invalid for property type \"{Alias}\"."); throw new NotSupportedException($"Variation {variation} is invalid for property type \"{Alias}\".");

View File

@@ -80,8 +80,9 @@ namespace Umbraco.Core.Models
item.IsPublishing = IsPublishing; item.IsPublishing = IsPublishing;
// fixme redo this entirely!!! // fixme redo this entirely!!!
using (new WriteLock(_addLocker)) try
{ {
_addLocker.EnterWriteLock();
var key = GetKeyForItem(item); var key = GetKeyForItem(item);
if (key != null) if (key != null)
{ {
@@ -105,6 +106,11 @@ namespace Umbraco.Core.Models
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
} }
finally
{
if (_addLocker.IsWriteLockHeld)
_addLocker.ExitWriteLock();
}
} }
/// <summary> /// <summary>

View File

@@ -3,17 +3,11 @@ using System.Collections.Generic;
namespace Umbraco.Core.Models.PublishedContent namespace Umbraco.Core.Models.PublishedContent
{ {
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
/// Represents a cached content. /// Represents a cached content.
/// </summary> /// </summary>
/// <remarks>
/// <para>SD: A replacement for INode which needs to occur since INode doesn't contain the document type alias
/// and INode is poorly formatted with mutable properties (i.e. Lists instead of IEnumerable).</para>
/// <para>Stephan: initially, that was for cached published content only. Now, we're using it also for
/// cached preview (so, maybe unpublished) content. A better name would therefore be ICachedContent, as
/// has been suggested. However, can't change now. Maybe in v7?</para>
/// </remarks>
public interface IPublishedContent : IPublishedElement public interface IPublishedContent : IPublishedElement
{ {
#region Content #region Content
@@ -38,6 +32,8 @@ namespace Umbraco.Core.Models.PublishedContent
int Level { get; } int Level { get; }
string Url { get; } string Url { get; }
IReadOnlyDictionary<string, PublishedCultureName> CultureNames { get; }
/// <summary> /// <summary>
/// Gets a value indicating whether the content is a content (aka a document) or a media. /// Gets a value indicating whether the content is a content (aka a document) or a media.
/// </summary> /// </summary>

View File

@@ -21,7 +21,7 @@
/// <para>Other caches that get their raw value from the database would consider that a property has "no /// <para>Other caches that get their raw value from the database would consider that a property has "no
/// value" if it is missing, null, or an empty string (including whitespace-only).</para> /// value" if it is missing, null, or an empty string (including whitespace-only).</para>
/// </remarks> /// </remarks>
bool HasValue(int? languageId = null, string segment = null); bool HasValue(string culture = null, string segment = null);
/// <summary> /// <summary>
/// Gets the source value of the property. /// Gets the source value of the property.
@@ -35,7 +35,7 @@
/// <para>If you're using that value, you're probably wrong, unless you're doing some internal /// <para>If you're using that value, you're probably wrong, unless you're doing some internal
/// Umbraco stuff.</para> /// Umbraco stuff.</para>
/// </remarks> /// </remarks>
object GetSourceValue(int? languageId = null, string segment = null); object GetSourceValue(string culture = null, string segment = null);
/// <summary> /// <summary>
/// Gets the object value of the property. /// Gets the object value of the property.
@@ -45,7 +45,7 @@
/// <para>It can be null, or any type of CLR object.</para> /// <para>It can be null, or any type of CLR object.</para>
/// <para>It has been fully prepared and processed by the appropriate converter.</para> /// <para>It has been fully prepared and processed by the appropriate converter.</para>
/// </remarks> /// </remarks>
object GetValue(int? languageId = null, string segment = null); object GetValue(string culture = null, string segment = null);
/// <summary> /// <summary>
/// Gets the XPath value of the property. /// Gets the XPath value of the property.
@@ -55,6 +55,6 @@
/// <para>It must be either null, or a string, or an XPathNavigator.</para> /// <para>It must be either null, or a string, or an XPathNavigator.</para>
/// <para>It has been fully prepared and processed by the appropriate converter.</para> /// <para>It has been fully prepared and processed by the appropriate converter.</para>
/// </remarks> /// </remarks>
object GetXPathValue(int? languageId = null, string segment = null); object GetXPathValue(string culture = null, string segment = null);
} }
} }

View File

@@ -54,7 +54,9 @@ namespace Umbraco.Core.Models.PublishedContent
public virtual int SortOrder => _content.SortOrder; public virtual int SortOrder => _content.SortOrder;
public virtual string Name => _content.Name; public virtual string Name => _content.Name;
public virtual IReadOnlyDictionary<string, PublishedCultureName> CultureNames => _content.CultureNames;
public virtual string UrlName => _content.UrlName; public virtual string UrlName => _content.UrlName;

View File

@@ -0,0 +1,19 @@
using System;
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Contains the culture specific data for a <see cref="IPublishedContent"/> item
/// </summary>
public struct PublishedCultureName
{
public PublishedCultureName(string name, string urlName) : this()
{
Name = name ?? throw new ArgumentNullException(nameof(name));
UrlName = urlName ?? throw new ArgumentNullException(nameof(urlName));
}
public string Name { get; }
public string UrlName { get; }
}
}

View File

@@ -53,15 +53,15 @@ namespace Umbraco.Core.Models.PublishedContent
public string Alias => PropertyType.Alias; public string Alias => PropertyType.Alias;
/// <inheritdoc /> /// <inheritdoc />
public abstract bool HasValue(int? languageId = null, string segment = null); public abstract bool HasValue(string culture = null, string segment = null);
/// <inheritdoc /> /// <inheritdoc />
public abstract object GetSourceValue(int? languageId = null, string segment = null); public abstract object GetSourceValue(string culture = null, string segment = null);
/// <inheritdoc /> /// <inheritdoc />
public abstract object GetValue(int? languageId = null, string segment = null); public abstract object GetValue(string culture = null, string segment = null);
/// <inheritdoc /> /// <inheritdoc />
public abstract object GetXPathValue(int? languageId = null, string segment = null); public abstract object GetXPathValue(string culture = null, string segment = null);
} }
} }

View File

@@ -20,20 +20,20 @@ namespace Umbraco.Core.Models.PublishedContent
private readonly Lazy<object> _objectValue; private readonly Lazy<object> _objectValue;
private readonly Lazy<object> _xpathValue; private readonly Lazy<object> _xpathValue;
public override object GetSourceValue(int? languageId = null, string segment = null) public override object GetSourceValue(string culture = null, string segment = null)
=> languageId == null & segment == null ? _sourceValue : null; => culture == null & segment == null ? _sourceValue : null;
public override bool HasValue(int? languageId = null, string segment = null) public override bool HasValue(string culture = null, string segment = null)
{ {
var sourceValue = GetSourceValue(languageId, segment); var sourceValue = GetSourceValue(culture, segment);
return sourceValue is string s ? !string.IsNullOrWhiteSpace(s) : sourceValue != null; return sourceValue is string s ? !string.IsNullOrWhiteSpace(s) : sourceValue != null;
} }
public override object GetValue(int? languageId = null, string segment = null) public override object GetValue(string culture = null, string segment = null)
=> languageId == null & segment == null ? _objectValue.Value : null; => culture == null & segment == null ? _objectValue.Value : null;
public override object GetXPathValue(int? languageId = null, string segment = null) public override object GetXPathValue(string culture = null, string segment = null)
=> languageId == null & segment == null ? _xpathValue.Value : null; => culture == null & segment == null ? _xpathValue.Value : null;
public RawValueProperty(PublishedPropertyType propertyType, IPublishedElement content, object sourceValue, bool isPreviewing = false) public RawValueProperty(PublishedPropertyType propertyType, IPublishedElement content, object sourceValue, bool isPreviewing = false)
: base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored : base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored

View File

@@ -14,14 +14,6 @@ namespace Umbraco.Core.Models
/// </summary> /// </summary>
Unknown, Unknown,
/// <summary>
/// Content Item Type
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Strings.ContentItemType)]
[FriendlyName("Content Item Type")]
[Obsolete("This is not used and will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
ContentItemType,
/// <summary> /// <summary>
/// Root /// Root
@@ -69,17 +61,7 @@ namespace Umbraco.Core.Models
[FriendlyName("Member Group")] [FriendlyName("Member Group")]
[UmbracoUdiType(Constants.UdiEntityType.MemberGroup)] [UmbracoUdiType(Constants.UdiEntityType.MemberGroup)]
MemberGroup, MemberGroup,
//TODO: What is a 'Content Item' supposed to be???
/// <summary>
/// Content Item
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Strings.ContentItem)]
[FriendlyName("Content Item")]
[Obsolete("This is not used and will be removed in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
ContentItem,
/// <summary> /// <summary>
/// "Media Type /// "Media Type
/// </summary> /// </summary>

View File

@@ -112,15 +112,6 @@ namespace Umbraco.Core.Models
} }
public static void ClearAllowedSections(this IUser user)
{
var allowed = user.AllowedSections.ToArray();
foreach (var s in allowed)
{
user.RemoveAllowedSection(s);
}
}
/// <summary> /// <summary>
/// Returns the culture info associated with this user, based on the language they're assigned to in the back office /// Returns the culture info associated with this user, based on the language they're assigned to in the back office
/// </summary> /// </summary>

View File

@@ -1,32 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a XSLT file
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class XsltFile : File, IXsltFile
{
public XsltFile(string path)
: this(path, (Func<File, string>) null)
{ }
internal XsltFile(string path, Func<File, string> getFileContent)
: base(path, getFileContent)
{ }
/// <summary>
/// Indicates whether the current entity has an identity, which in this case is a path/name.
/// </summary>
/// <remarks>
/// Overrides the default Entity identity check.
/// </remarks>
public override bool HasIdentity
{
get { return string.IsNullOrEmpty(Path) == false; }
}
}
}

View File

@@ -1,45 +0,0 @@
using System;
using NuGet;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.Packaging
{
internal class DefaultPackageContext : IPackageContext
{
public DefaultPackageContext(Func<string, string> mapPath)
{}
private readonly string _localPackageRepoFolderPath;
private readonly string _pluginInstallFolderPath;
private readonly Lazy<IPackageManager> _localPackageManager;
private readonly Lazy<IPackageRepository> _localPackageRepository;
private readonly Lazy<IPackageManager> _publicPackageManager;
private readonly Lazy<IPackageManager> _privatePackageManager;
private readonly Lazy<IPackageRepository> _publicPackageRepository;
private readonly Lazy<IPackageRepository> _sprivatePackageRepository;
/// <summary>
/// Gets the local path resolver.
/// </summary>
public IPackagePathResolver LocalPathResolver
{
get { return ((PackageManager)LocalPackageManager).PathResolver; }
}
/// <summary>
/// Gets the local package manager.
/// </summary>
public IPackageManager LocalPackageManager
{
get { return _localPackageManager.Value; }
}
/// <summary>
/// Gets the public package manager.
/// </summary>
public IPackageManager PublicPackageManager
{
get { return _publicPackageManager.Value; }
}
}
}

View File

@@ -1,11 +0,0 @@
using NuGet;
namespace Umbraco.Core.Packaging
{
internal interface IPackageContext
{
IPackageManager LocalPackageManager { get; }
IPackageManager PublicPackageManager { get; }
IPackagePathResolver LocalPathResolver { get; }
}
}

View File

@@ -17,10 +17,10 @@ namespace Umbraco.Core
public const string NodeXml = /*TableNamePrefix*/ "cms" + "ContentXml"; public const string NodeXml = /*TableNamePrefix*/ "cms" + "ContentXml";
public const string NodePreviewXml = /*TableNamePrefix*/ "cms" + "PreviewXml"; // fixme dbfix kill merge with ContentXml public const string NodePreviewXml = /*TableNamePrefix*/ "cms" + "PreviewXml"; // fixme dbfix kill merge with ContentXml
public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; // fixme dbfixrename and split uElementType, uDocumentType public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; // fixme dbfix rename and split uElementType, uDocumentType
public const string ContentChildType = /*TableNamePrefix*/ "cms" + "ContentTypeAllowedContentType"; public const string ContentChildType = /*TableNamePrefix*/ "cms" + "ContentTypeAllowedContentType";
public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme dbfixmust rename corresponding DTO public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme dbfix must rename corresponding DTO
public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme dbfixwhy can't we just use uNode for this? public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme dbfix why can't we just use uNode for this?
public const string DataType = TableNamePrefix + "DataType"; public const string DataType = TableNamePrefix + "DataType";
public const string Template = /*TableNamePrefix*/ "cms" + "Template"; public const string Template = /*TableNamePrefix*/ "cms" + "Template";
@@ -28,6 +28,7 @@ namespace Umbraco.Core
public const string ContentVersion = TableNamePrefix + "ContentVersion"; public const string ContentVersion = TableNamePrefix + "ContentVersion";
public const string ContentVersionCultureVariation = TableNamePrefix + "ContentVersionCultureVariation"; public const string ContentVersionCultureVariation = TableNamePrefix + "ContentVersionCultureVariation";
public const string Document = TableNamePrefix + "Document"; public const string Document = TableNamePrefix + "Document";
public const string DocumentCultureVariation = TableNamePrefix + "DocumentCultureVariation";
public const string DocumentVersion = TableNamePrefix + "DocumentVersion"; public const string DocumentVersion = TableNamePrefix + "DocumentVersion";
public const string MediaVersion = TableNamePrefix + "MediaVersion"; public const string MediaVersion = TableNamePrefix + "MediaVersion";

View File

@@ -16,6 +16,12 @@ namespace Umbraco.Core.Persistence.Dtos
[Column("published")] [Column("published")]
public bool Published { get; set; } public bool Published { get; set; }
/// <summary>
/// Stores serialized JSON representing the content item's property and culture name values
/// </summary>
/// <remarks>
/// Pretty much anything that would require a 1:M lookup is serialized here
/// </remarks>
[Column("data")] [Column("data")]
[SpecialDbType(SpecialDbTypes.NTEXT)] [SpecialDbType(SpecialDbTypes.NTEXT)]
public string Data { get; set; } public string Data { get; set; }

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Dtos
[ExplicitColumns] [ExplicitColumns]
internal class ContentVersionCultureVariationDto internal class ContentVersionCultureVariationDto
{ {
private const string TableName = Constants.DatabaseSchema.Tables.ContentVersionCultureVariation; public const string TableName = Constants.DatabaseSchema.Tables.ContentVersionCultureVariation;
[Column("id")] [Column("id")]
[PrimaryKeyColumn] [PrimaryKeyColumn]
@@ -25,21 +25,21 @@ namespace Umbraco.Core.Persistence.Dtos
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")] [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")]
public int LanguageId { get; set; } public int LanguageId { get; set; }
// this is convenient to carry the culture around, but has no db counterpart
[Ignore]
public string Culture { get; set; }
[Column("name")] [Column("name")]
[NullSetting(NullSetting = NullSettings.Null)]
public string Name { get; set; } public string Name { get; set; }
[Column("available")] [Column("date")]
public bool Available { get; set; } public DateTime Date { get; set; }
[Column("availableDate")]
[NullSetting(NullSetting = NullSettings.Null)]
public DateTime? AvailableDate { get; set; }
// fixme want?
[Column("availableUserId")] [Column("availableUserId")]
// [ForeignKey(typeof(UserDto))] -- there is no foreign key so we can delete users without deleting associated content // [ForeignKey(typeof(UserDto))] -- there is no foreign key so we can delete users without deleting associated content
//[NullSetting(NullSetting = NullSettings.Null)] //[NullSetting(NullSetting = NullSettings.Null)]
public int AvailableUserId { get; set; } public int PublishedUserId { get; set; }
[Column("edited")] [Column("edited")]
public bool Edited { get; set; } public bool Edited { get; set; }

View File

@@ -0,0 +1,34 @@
using NPoco;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Persistence.Dtos
{
[TableName(TableName)]
[PrimaryKey("id")]
[ExplicitColumns]
internal class DocumentCultureVariationDto
{
private const string TableName = Constants.DatabaseSchema.Tables.DocumentCultureVariation;
[Column("id")]
[PrimaryKeyColumn]
public int Id { get; set; }
[Column("nodeId")]
[ForeignKey(typeof(NodeDto))]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_NodeId", ForColumns = "nodeId,languageId")]
public int NodeId { get; set; }
[Column("languageId")]
[ForeignKey(typeof(LanguageDto))]
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")]
public int LanguageId { get; set; }
// this is convenient to carry the culture around, but has no db counterpart
[Ignore]
public string Culture { get; set; }
[Column("edited")]
public bool Edited { get; set; }
}
}

View File

@@ -34,18 +34,6 @@ namespace Umbraco.Core.Persistence.Dtos
[NullSetting(NullSetting = NullSettings.Null)] [NullSetting(NullSetting = NullSettings.Null)]
public string Name { get; set; } public string Name { get; set; }
[Column("macroScriptType")]
[NullSetting(NullSetting = NullSettings.Null)]
public string ScriptType { get; set; }
[Column("macroScriptAssembly")]
[NullSetting(NullSetting = NullSettings.Null)]
public string ScriptAssembly { get; set; }
[Column("macroXSLT")]
[NullSetting(NullSetting = NullSettings.Null)]
public string Xslt { get; set; }
[Column("macroCacheByPage")] [Column("macroCacheByPage")]
[Constraint(Default = "1")] [Constraint(Default = "1")]
public bool CacheByPage { get; set; } public bool CacheByPage { get; set; }
@@ -58,10 +46,13 @@ namespace Umbraco.Core.Persistence.Dtos
[Constraint(Default = "0")] [Constraint(Default = "0")]
public bool DontRender { get; set; } public bool DontRender { get; set; }
//TODO: Rename this column! - actually please revamp all of the macros! :) [Column("macroSource")]
[Column("macroPython")] [NullSetting(NullSetting = NullSettings.NotNull)]
[NullSetting(NullSetting = NullSettings.Null)] public string MacroSource { get; set; }
public string MacroFilePath { get; set; }
[Column("macroType")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int MacroType { get; set; }
[ResultColumn] [ResultColumn]
[Reference(ReferenceType.Many, ReferenceMemberName = "Macro")] [Reference(ReferenceType.Many, ReferenceMemberName = "Macro")]

Some files were not shown because too many files have changed in this diff Show More