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
+13
View File
@@ -15,3 +15,16 @@ indent_size = 4
# Trim trailing whitespace, limited support.
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
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
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.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
src/Umbraco.Web.UI.Client/docs/api
src/*.boltdata/
+1 -1
View File
@@ -43,7 +43,7 @@
<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="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="NPoco" version="[3.9.3,3.666666)" />
<dependency id="NuGet.Core" version="[2.14.0,2.666666)" />
+2 -186
View File
@@ -4,8 +4,8 @@
<configSections>
<section name="BaseRestExtensions" 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)">
<section name="umbraco.presentation.Properties.Settings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
</sectionGroup>
@@ -67,190 +67,6 @@
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
<sessionState customProvider="DefaultSessionProvider" xdt:Locator="Match(customProvider)" xdt:Transform="Remove"/>
<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" />
@@ -86,9 +86,6 @@
<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: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"
xdt:Locator="Match(application,alias,type)"
@@ -5,4 +5,6 @@
</content>
<webservices xdt:Transform="Remove" />
<repositories xdt:Transform="Remove" />
</settings>
-2
View File
@@ -372,8 +372,6 @@
Write-Host "Add web.config transforms to NuGet package"
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",
+2 -44
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")]
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")]
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")]
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";
[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")]
public const string ContentTypeCacheKey = "UmbracoContentType";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
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 KeyToIdCacheKey = "UK2I__";
}
@@ -24,8 +24,13 @@ namespace Umbraco.Core.Cache
protected abstract object GetEntry(string key);
// read-write lock the underlying cache
protected abstract IDisposable ReadLock { get; }
protected abstract IDisposable WriteLock { get; }
//protected abstract IDisposable ReadLock { 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)
{
@@ -88,21 +93,31 @@ namespace Umbraco.Core.Cache
public virtual void ClearAllCache()
{
using (WriteLock)
try
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheItem(string key)
{
var cacheKey = GetCacheKey(key);
using (WriteLock)
try
{
EnterWriteLock();
RemoveEntry(cacheKey);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes(string typeName)
@@ -110,15 +125,16 @@ namespace Umbraco.Core.Cache
var type = TypeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
using (WriteLock)
try
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
// entry.Value is Lazy<object> and not null, its value may be null
// remove null values as well, does not hurt
// 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
// otherwise remove exact types (not inherited types)
@@ -127,14 +143,19 @@ namespace Umbraco.Core.Cache
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes<T>()
{
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
using (WriteLock)
try
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
@@ -142,7 +163,7 @@ namespace Umbraco.Core.Cache
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// 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
// otherwise remove exact types (not inherited types)
@@ -151,6 +172,10 @@ namespace Umbraco.Core.Cache
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
@@ -158,8 +183,9 @@ namespace Umbraco.Core.Cache
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
var plen = CacheItemPrefix.Length + 1;
using (WriteLock)
try
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x =>
{
@@ -167,7 +193,7 @@ namespace Umbraco.Core.Cache
// remove null values as well, does not hurt
// compare on exact type, don't use "is"
// 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 T is an interface remove anything that implements that interface
@@ -178,30 +204,44 @@ namespace Umbraco.Core.Cache
}))
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
var plen = CacheItemPrefix.Length + 1;
using (WriteLock)
try
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
public virtual void ClearCacheByKeyExpression(string regexString)
{
var plen = CacheItemPrefix.Length + 1;
using (WriteLock)
try
{
EnterWriteLock();
foreach (var entry in GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray())
RemoveEntry((string) entry.Key);
}
finally
{
ExitWriteLock();
}
}
#endregion
@@ -212,12 +252,18 @@ namespace Umbraco.Core.Cache
{
var plen = CacheItemPrefix.Length + 1;
IEnumerable<DictionaryEntry> entries;
using (ReadLock)
try
{
EnterReadLock();
entries = GetDictionaryEntries()
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked
}
finally
{
ExitReadLock();
}
return entries
.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
@@ -228,12 +274,17 @@ namespace Umbraco.Core.Cache
const string prefix = CacheItemPrefix + "-";
var plen = prefix.Length;
IEnumerable<DictionaryEntry> entries;
using (ReadLock)
try
{
EnterReadLock();
entries = GetDictionaryEntries()
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
.ToArray(); // evaluate while locked
}
finally
{
ExitReadLock();
}
return entries
.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
@@ -243,10 +294,15 @@ namespace Umbraco.Core.Cache
{
cacheKey = GetCacheKey(cacheKey);
Lazy<object> result;
using (ReadLock)
try
{
EnterReadLock();
result = GetEntry(cacheKey) as Lazy<object>; // null if key not found
}
finally
{
ExitReadLock();
}
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
}
@@ -79,24 +79,26 @@ namespace Umbraco.Core.Cache
#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
get { return WriteLock; }
if (HasContextItems)
{
System.Threading.Monitor.Enter(ContextItems.SyncRoot, ref _entered);
}
}
protected override IDisposable WriteLock
{
// 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.
protected override void ExitReadLock() => ExitWriteLock();
get
protected override void ExitWriteLock()
{
if (_entered)
{
return HasContextItems
? (IDisposable) new MonitorLock(ContextItems.SyncRoot)
: new NoopLocker();
_entered = false;
System.Threading.Monitor.Exit(ContextItems.SyncRoot);
}
}
@@ -113,8 +115,9 @@ namespace Umbraco.Core.Cache
Lazy<object> result;
using (WriteLock)
try
{
EnterWriteLock();
result = ContextItems[cacheKey] as Lazy<object>; // null if key not found
// cannot create value within the lock, so if result.IsValueCreated is false, just
@@ -127,6 +130,10 @@ namespace Umbraco.Core.Cache
ContextItems[cacheKey] = result;
}
}
finally
{
ExitWriteLock();
}
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
// exceptions (but try again and again) and silently eat them - however at
@@ -50,14 +50,26 @@ namespace Umbraco.Core.Cache
#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
@@ -118,10 +130,16 @@ namespace Umbraco.Core.Cache
// 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
// it's worth it, though...
using (new ReadLock(_locker))
try
{
_locker.EnterReadLock();
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);
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 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!
_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)
@@ -37,20 +37,32 @@ namespace Umbraco.Core.Cache
public virtual void ClearAllCache()
{
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
MemoryCache.DisposeIfDisposable();
MemoryCache = new MemoryCache("in-memory");
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public virtual void ClearCacheItem(string key)
{
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
if (MemoryCache[key] == null) return;
MemoryCache.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes(string typeName)
@@ -58,8 +70,9 @@ namespace Umbraco.Core.Cache
var type = TypeFinder.GetTypeByName(typeName);
if (type == null) return;
var isInterface = type.IsInterface;
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
foreach (var key in MemoryCache
.Where(x =>
{
@@ -76,12 +89,18 @@ namespace Umbraco.Core.Cache
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes<T>()
{
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
var typeOfT = typeof (T);
var isInterface = typeOfT.IsInterface;
foreach (var key in MemoryCache
@@ -101,12 +120,18 @@ namespace Umbraco.Core.Cache
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
var typeOfT = typeof(T);
var isInterface = typeOfT.IsInterface;
foreach (var key in MemoryCache
@@ -127,30 +152,47 @@ namespace Umbraco.Core.Cache
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
foreach (var key in MemoryCache
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
public virtual void ClearCacheByKeyExpression(string regexString)
{
using (new WriteLock(_locker))
try
{
_locker.EnterWriteLock();
foreach (var key in MemoryCache
.Where(x => Regex.IsMatch(x.Key, regexString))
.Select(x => x.Key)
.ToArray()) // ToArray required to remove
MemoryCache.Remove(key);
}
finally
{
if (_locker.IsWriteLockHeld)
_locker.ExitWriteLock();
}
}
#endregion
@@ -160,12 +202,18 @@ namespace Umbraco.Core.Cache
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
KeyValuePair<string, object>[] entries;
using (new ReadLock(_locker))
try
{
_locker.EnterReadLock();
entries = MemoryCache
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
.ToArray(); // evaluate while locked
}
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
return entries
.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
@@ -175,12 +223,18 @@ namespace Umbraco.Core.Cache
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
{
KeyValuePair<string, object>[] entries;
using (new ReadLock(_locker))
try
{
_locker.EnterReadLock();
entries = MemoryCache
.Where(x => Regex.IsMatch(x.Key, regexString))
.ToArray(); // evaluate while locked
}
finally
{
if (_locker.IsReadLockHeld)
_locker.ExitReadLock();
}
return entries
.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
@@ -190,10 +244,16 @@ namespace Umbraco.Core.Cache
public object GetCacheItem(string cacheKey)
{
Lazy<object> result;
using (new ReadLock(_locker))
try
{
_locker.EnterReadLock();
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
}
@@ -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;
}
}
@@ -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>
public bool Remove(T item)
{
using (new WriteLock(_instanceLocker))
try
{
_instanceLocker.EnterWriteLock();
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>
public void Add(T item)
{
using (new WriteLock(_instanceLocker))
try
{
_instanceLocker.EnterWriteLock();
_innerSet.Add(item);
}
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
}
/// <summary>
@@ -101,13 +113,20 @@ namespace Umbraco.Core.Collections
{
var clone = GetThreadSafeClone();
if (clone.Contains(item)) return false;
using (new WriteLock(_instanceLocker))
try
{
_instanceLocker.EnterWriteLock();
//double check
if (_innerSet.Contains(item)) return false;
_innerSet.Add(item);
return true;
}
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
}
/// <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>
public void Clear()
{
using (new WriteLock(_instanceLocker))
try
{
_instanceLocker.EnterWriteLock();
_innerSet.Clear();
}
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
}
/// <summary>
@@ -147,10 +172,16 @@ namespace Umbraco.Core.Collections
private HashSet<T> GetThreadSafeClone()
{
HashSet<T> clone = null;
using (new WriteLock(_instanceLocker))
try
{
_instanceLocker.EnterWriteLock();
clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
}
finally
{
if (_instanceLocker.IsWriteLockHeld)
_instanceLocker.ExitWriteLock();
}
return clone;
}
@@ -76,7 +76,6 @@ namespace Umbraco.Core.Composing.CompositionRoots
container.RegisterSingleton<IPartialViewRepository, PartialViewRepository>();
container.RegisterSingleton<IScriptRepository, ScriptRepository>();
container.RegisterSingleton<IStylesheetRepository, StylesheetRepository>();
container.RegisterSingleton<IXsltFileRepository, XsltFileRepository>();
}
}
}
@@ -311,15 +311,15 @@ namespace Umbraco.Core.Composing
// we HAVE to let LightInject throw - and catch at THE OUTERMOST if InvalidOperationException in LightInject.Anything!
return factory.GetInstance(tService, serviceName, args);
try
{
return factory.GetInstance(tService, serviceName, args);
}
catch (Exception e)
{
LightInjectException.TryThrow(e, implementingType);
throw;
}
//try
//{
// return factory.GetInstance(tService, serviceName, args);
//}
//catch (Exception e)
//{
// LightInjectException.TryThrow(e, implementingType);
// throw;
//}
}
/// <summary>
@@ -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; }
}
}
}
@@ -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; }
}
}
}
@@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IDeveloperSection : IUmbracoConfigurationSection
{
IEnumerable<IFileExtension> AppCodeFileExtensions { get; }
}
}
@@ -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; }
}
}
@@ -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; }
}
}
@@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IRepositoriesSection : IUmbracoConfigurationSection
{
IEnumerable<IRepository> Repositories { get; }
}
}
@@ -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; }
}
}
@@ -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; }
}
}
@@ -4,13 +4,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface ITemplatesSection : IUmbracoConfigurationSection
{
bool UseAspNetMasterPages { get; }
bool EnableSkinSupport { get; }
RenderingEngine DefaultRenderingEngine { get; }
[Obsolete("This has no affect and will be removed in future versions")]
bool EnableTemplateFolders { get; }
}
}
@@ -14,18 +14,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IRequestHandlerSection RequestHandler { get; }
ITemplatesSection Templates { get; }
IDeveloperSection Developer { get; }
ILoggingSection Logging { get; }
IScheduledTasksSection ScheduledTasks { get; }
IDistributedCallSection DistributedCall { get; }
IRepositoriesSection PackageRepositories { get; }
IProvidersSection Providers { get; }
IWebRoutingSection WebRouting { get; }
@@ -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();
}
}
}
@@ -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; }
}
}
}
@@ -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;
}
}
}
@@ -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; }
}
}
}
@@ -41,7 +41,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("authCookieName")]
internal InnerTextConfigurationElement<string> AuthCookieName
{
get { return GetOptionalTextElement("authCookieName", Constants.Web.AuthCookieName); }
get { return GetOptionalTextElement("authCookieName", "UMB_UCONTEXT"); }
}
[ConfigurationProperty("authCookieDomain")]
@@ -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();
}
}
}
@@ -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;
}
}
}
}
@@ -5,50 +5,16 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
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)]
internal InnerTextConfigurationElement<RenderingEngine> DefaultRenderingEngine
{
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
{
get { return DefaultRenderingEngine; }
}
[Obsolete("This has no affect and will be removed in future versions")]
bool ITemplatesSection.EnableTemplateFolders
{
get { return EnableTemplateFolders; }
}
}
}
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
internal BackOfficeElement BackOffice
{
get { return (BackOfficeElement)this["backOffice"]; }
}
}
[ConfigurationProperty("content")]
internal ContentElement Content
@@ -37,14 +37,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return (TemplatesElement)this["templates"]; }
}
[ConfigurationProperty("developer")]
internal DeveloperElement Developer
{
get { return (DeveloperElement)this["developer"]; }
}
[ConfigurationProperty("logging")]
internal LoggingElement Logging
{
@@ -57,55 +50,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
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")]
internal ProvidersElement Providers
{
@@ -141,11 +85,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IBackOfficeSection IUmbracoSettingsSection.BackOffice
{
get { return BackOffice; }
}
IDeveloperSection IUmbracoSettingsSection.Developer
{
get { return Developer; }
}
ILoggingSection IUmbracoSettingsSection.Logging
@@ -157,17 +96,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return ScheduledTasks; }
}
IDistributedCallSection IUmbracoSettingsSection.DistributedCall
{
get { return DistributedCall; }
}
IRepositoriesSection IUmbracoSettingsSection.PackageRepositories
{
get { return PackageRepositories; }
}
IProvidersSection IUmbracoSettingsSection.Providers
{
get { return Providers; }
+1 -3
View File
@@ -121,9 +121,7 @@
public const string Templates = "templates";
public const string RelationTypes = "relationTypes";
public const string Xslt = "xslt";
public const string Languages = "languages";
/// <summary>
-1
View File
@@ -21,7 +21,6 @@
public const string StylesheetFileSystem = "StylesheetFileSystem";
public const string MasterpageFileSystem = "MasterpageFileSystem";
public const string ViewFileSystem = "ViewFileSystem";
public const string XsltFileSystem = "XsltFileSystem";
public const string JavascriptLibraryFileSystem = "JavascriptLibraryFileSystem";
}
}
@@ -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";
}
}
}
-7
View File
@@ -23,13 +23,6 @@ namespace Umbraco.Core
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";
}
}
}
+22
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;
}
}
-15
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>
/// <param name="e">The items.</param>
/// <param name="f">The select child.</param>
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Events
/// <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.
/// </summary>
public string ItemKey { get; set; }
public string MacroSource { get; set; }
/// <summary>
/// Exception raised.
+2 -16
View File
@@ -26,10 +26,8 @@ namespace Umbraco.Core.IO
private ShadowWrapper _partialViewsFileSystem;
private ShadowWrapper _stylesheetsFileSystem;
private ShadowWrapper _scriptsFileSystem;
private ShadowWrapper _xsltFileSystem;
private ShadowWrapper _masterPagesFileSystem;
private ShadowWrapper _mvcViewsFileSystem;
private ShadowWrapper _javaScriptLibraryFileSystem;
// well-known file systems lazy initialization
private object _wkfsLock = new object();
@@ -103,16 +101,7 @@ namespace Umbraco.Core.IO
return _scriptsFileSystem;
}
}
public IFileSystem XsltFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _xsltFileSystem;
}
}
public IFileSystem MasterPagesFileSystem
{
get
@@ -163,7 +152,6 @@ namespace Umbraco.Core.IO
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
var javaScriptLibraryFileSystem = new PhysicalFileSystem(SystemDirectories.JavaScriptLibrary);
@@ -172,7 +160,6 @@ namespace Umbraco.Core.IO
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", () => IsScoped());
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", () => IsScoped());
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", () => IsScoped());
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", () => IsScoped());
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", () => IsScoped());
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped());
_javascriptLibraryFileSystem = new ShadowWrapper(javaScriptLibraryFileSystem, "Lib", () => IsScoped());
@@ -366,14 +353,13 @@ namespace Umbraco.Core.IO
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
var typed = _wrappers.ToArray();
var wrappers = new ShadowWrapper[typed.Length + 7];
var wrappers = new ShadowWrapper[typed.Length + 6];
var i = 0;
while (i < typed.Length) wrappers[i] = typed[i++];
wrappers[i++] = _macroPartialFileSystem;
wrappers[i++] = _partialViewsFileSystem;
wrappers[i++] = _stylesheetsFileSystem;
wrappers[i++] = _scriptsFileSystem;
wrappers[i++] = _xsltFileSystem;
wrappers[i++] = _masterPagesFileSystem;
wrappers[i] = _mvcViewsFileSystem;
+1 -7
View File
@@ -27,13 +27,7 @@ namespace Umbraco.Core.IO
{
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)
{
return GetFilePath(t.Alias);
+10 -10
View File
@@ -335,35 +335,35 @@ namespace Umbraco.Core.IO
// 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 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);
property.SetValue(GetUrl(filepath), languageId, segment);
SetUploadFile(content, property, filepath, filestream, languageId, segment);
property.SetValue(GetUrl(filepath), culture, 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);
// 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)
DeleteFile(oldpath);
property.SetValue(GetUrl(filepath), languageId, segment);
property.SetValue(GetUrl(filepath), culture, segment);
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
// 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
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, languageId, segment);
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, culture, segment);
}
#endregion
-2
View File
@@ -46,8 +46,6 @@ namespace Umbraco.Core.IO
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
public static string Packages => IOHelper.ReturnPath("umbracoPackagesPath", Data + IOHelper.DirSepChar + "packages");
+3 -4
View File
@@ -67,10 +67,9 @@ namespace Umbraco.Core.IO
modelNamespaceAlias = "ContentModels";
// either
// @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
// @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ModelClass>
// @inherits Umbraco.Web.Mvc.UmbracoTemplatePage<ContentModels.ModelClass>
content.Append("@inherits Umbraco.Web.Mvc.UmbracoTemplatePage");
// @inherits Umbraco.Web.Mvc.UmbracoViewPage
// @inherits Umbraco.Web.Mvc.UmbracoViewPage<ModelClass>
content.Append("@inherits Umbraco.Web.Mvc.UmbracoViewPage");
if (modelClassName.IsNullOrWhiteSpace() == false)
{
content.Append("<");
@@ -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
// {
// }
//}
+1 -1
View File
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Macros
// Check whether it's a single tag (<?.../>) or a tag with children (<?..>...</?...>)
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
// following format: "<?UMBRACO_MACRO ...><IMG SRC="..."..></?UMBRACO_MACRO>", so we
// need to delete extra information inserted which is the image-tag and the closing
-17
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; }
}
}
@@ -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;
}
}
}
@@ -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)
{ }
}
}
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -41,9 +41,9 @@ namespace Umbraco.Core.Media
/// </summary>
/// <param name="content">The content item.</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>
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 (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias));
@@ -53,7 +53,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing
// reset
Reset(content, autoFillConfig, languageId, segment);
Reset(content, autoFillConfig, culture, segment);
}
/// <summary>
@@ -61,14 +61,14 @@ namespace Umbraco.Core.Media
/// </summary>
/// <param name="content">The content item.</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>
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 (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
ResetProperties(content, autoFillConfig, languageId, segment);
ResetProperties(content, autoFillConfig, culture, segment);
}
/// <summary>
@@ -77,9 +77,9 @@ namespace Umbraco.Core.Media
/// <param name="content">The content item.</param>
/// <param name="propertyTypeAlias">The property type alias.</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>
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 (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias));
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing
// populate
Populate(content, autoFillConfig, filepath, languageId, segment);
Populate(content, autoFillConfig, filepath, culture, segment);
}
/// <summary>
@@ -102,9 +102,9 @@ namespace Umbraco.Core.Media
/// <param name="propertyTypeAlias">The property type alias.</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="languageId">Variation language.</param>
/// <param name="culture">Variation language.</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 (propertyTypeAlias == null) throw new ArgumentNullException(nameof(propertyTypeAlias));
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing
// populate
Populate(content, autoFillConfig, filepath, filestream, languageId, segment);
Populate(content, autoFillConfig, filepath, filestream, culture, segment);
}
/// <summary>
@@ -127,9 +127,9 @@ namespace Umbraco.Core.Media
/// <param name="autoFillConfig">The auto-fill configuration.</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>
/// <param name="languageId">Variation language.</param>
/// <param name="culture">Variation language.</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 (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
@@ -137,7 +137,7 @@ namespace Umbraco.Core.Media
// no file = reset, file = auto-fill
if (filepath.IsNullOrWhiteSpace())
{
ResetProperties(content, autoFillConfig, languageId, segment);
ResetProperties(content, autoFillConfig, culture, segment);
}
else
{
@@ -148,13 +148,13 @@ namespace Umbraco.Core.Media
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
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)
{
_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="filepath">The filesystem-relative filepath, or null to clear properties.</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>
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 (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
@@ -176,50 +176,50 @@ namespace Umbraco.Core.Media
// no file = reset, file = auto-fill
if (filepath.IsNullOrWhiteSpace() || filestream == null)
{
ResetProperties(content, autoFillConfig, languageId, segment);
ResetProperties(content, autoFillConfig, culture, segment);
}
else
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
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 (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
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))
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))
content.Properties[autoFillConfig.LengthFieldAlias].SetValue(length, languageId, segment);
content.Properties[autoFillConfig.LengthFieldAlias].SetValue(length, culture, segment);
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 (autoFillConfig == null) throw new ArgumentNullException(nameof(autoFillConfig));
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))
content.Properties[autoFillConfig.HeightFieldAlias].SetValue(string.Empty, languageId, segment);
content.Properties[autoFillConfig.HeightFieldAlias].SetValue(string.Empty, culture, segment);
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))
content.Properties[autoFillConfig.ExtensionFieldAlias].SetValue(string.Empty, languageId, segment);
content.Properties[autoFillConfig.ExtensionFieldAlias].SetValue(string.Empty, culture, segment);
}
}
}
@@ -82,7 +82,8 @@ namespace Umbraco.Core.Migrations.Install
typeof (UserLoginDto),
typeof (ConsentDto),
typeof (AuditEntryDto),
typeof (ContentVersionCultureVariationDto)
typeof (ContentVersionCultureVariationDto),
typeof (DocumentCultureVariationDto)
};
/// <summary>
@@ -116,10 +116,12 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain<SuperZero>("{9DF05B77-11D1-475C-A00A-B656AF7E0908}");
Chain<PropertyEditorsMigration>("{6FE3EF34-44A0-4992-B379-B40BC4EF1C4D}");
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)
Chain("{941B2ABA-2D06-4E04-81F5-74224F1DB037}");
Chain("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
// UPGRADE FROM 7, MORE RECENT
@@ -201,12 +203,19 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain<RenamePreviewFolder>("{79591E91-01EA-43F7-AC58-7BD286DB1E77}");
// 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 !
// 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}");
}
}
}
@@ -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?
}
}
}
@@ -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
{
public class AddContentVariationTable : MigrationBase
public class AddVariationTables2 : MigrationBase
{
public AddContentVariationTable(IMigrationContext context)
public AddVariationTables2(IMigrationContext context)
: base(context)
{ }
public override void Migrate()
{
Create.Table<ContentVersionCultureVariationDto>().Do();
Create.Table<DocumentCultureVariationDto>().Do();
// fixme - data migration?
}
@@ -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();
}
}
}
}
@@ -67,13 +67,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
.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()
{
const string sql = @"delete from cmsPreviewXml where versionId in (
+183 -121
View File
@@ -20,7 +20,8 @@ namespace Umbraco.Core.Models
private PublishedState _publishedState;
private DateTime? _releaseDate;
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>();
@@ -30,8 +31,8 @@ namespace Umbraco.Core.Models
/// <param name="name">Name of the content</param>
/// <param name="parent">Parent <see cref="IContent"/> object</param>
/// <param name="contentType">ContentType for the current Content object</param>
public Content(string name, IContent parent, IContentType contentType)
: this(name, parent, contentType, new PropertyCollection())
public Content(string name, IContent parent, IContentType contentType, string culture = null)
: this(name, parent, contentType, new PropertyCollection(), culture)
{ }
/// <summary>
@@ -41,8 +42,8 @@ namespace Umbraco.Core.Models
/// <param name="parent">Parent <see cref="IContent"/> object</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param>
public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties)
: base(name, parent, contentType, properties)
public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parent, contentType, properties, culture)
{
_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
_publishedState = PublishedState.Unpublished;
@@ -55,8 +56,8 @@ namespace Umbraco.Core.Models
/// <param name="name">Name of the content</param>
/// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param>
public Content(string name, int parentId, IContentType contentType)
: this(name, parentId, contentType, new PropertyCollection())
public Content(string name, int parentId, IContentType contentType, string culture = null)
: this(name, parentId, contentType, new PropertyCollection(), culture)
{ }
/// <summary>
@@ -66,8 +67,8 @@ namespace Umbraco.Core.Models
/// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param>
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties)
: base(name, parentId, contentType, properties)
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parentId, contentType, properties, culture)
{
_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType));
_publishedState = PublishedState.Unpublished;
@@ -195,73 +196,116 @@ namespace Umbraco.Core.Models
[IgnoreDataMember]
public ITemplate PublishTemplate { get; internal set; }
[IgnoreDataMember]
public string PublishName { get; internal set; }
/// <inheritdoc/>
[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
// sets publish infos
// internal for repositories
internal void SetPublishName(int? languageId, string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullOrEmptyException(nameof(name));
if (languageId == null)
// clear by clearing name
internal void SetPublishInfos(string culture, string name, DateTime date)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentNullOrEmptyException(nameof(name));
// 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;
return;
}
PublishDate = date;
}
// private method, assume that culture is valid
if (_publishNames == null)
_publishNames = new Dictionary<int, string>();
_publishNames[languageId.Value] = name;
}
if (culture != null)
{
// private method, assume that culture is valid
// clears a publish name
private void ClearPublishName(int? languageId)
if (_publishInfos == null)
_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;
return;
}
if (_publishNames == null) return;
_publishNames.Remove(languageId.Value);
if (_publishNames.Count == 0)
_publishNames = null;
if (_publishInfos == null) return;
_publishInfos.Remove(culture);
if (_publishInfos.Count == 0)
_publishInfos = null;
}
// clears all publish names
private void ClearPublishNames()
{
PublishName = null;
_publishNames = null;
_publishInfos = null;
}
/// <inheritdoc />
public bool IsCultureAvailable(int? languageId)
=> !string.IsNullOrWhiteSpace(GetName(languageId));
public bool IsCulturePublished(string culture)
=> !string.IsNullOrWhiteSpace(GetPublishName(culture));
/// <inheritdoc />
public bool IsCulturePublished(int? languageId)
=> !string.IsNullOrWhiteSpace(GetPublishName(languageId));
public DateTime GetDateCulturePublished(string culture)
{
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]
public int PublishedVersionId { get; internal set; }
@@ -269,62 +313,80 @@ namespace Umbraco.Core.Models
public bool Blueprint { get; internal set; }
/// <inheritdoc />
public virtual bool PublishAllValues()
public virtual bool TryPublishAllValues()
{
// the values we want to publish should be valid
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)
foreach (var property in Properties)
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);
property.PublishAllValues();
_publishedState = PublishedState.Publishing;
return true;
}
/// <inheritdoc />
public virtual bool PublishValues(int? languageId = null, string segment = null)
{
// the variation should be supported by the content type
ContentType.ValidateVariation(languageId, segment, throwIfInvalid: true);
public virtual bool TryPublishValues(string culture = null, string segment = null)
{
// the variation should be supported by the content type
ContentType.ValidateVariation(culture, segment, throwIfInvalid: true);
// the values we want to publish should be valid
if (Validate(languageId, segment).Any())
return false;
// 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);
if (Validate(culture, segment).Any())
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.
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;
return true;
}
/// <inheritdoc />
public virtual bool PublishCultureValues(int? languageId = null)
{
public virtual bool PublishCultureValues(string culture = null)
{
// the values we want to publish should be valid
if (ValidateCulture(languageId).Any())
if (ValidateCulture(culture).Any())
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)
foreach (var property in Properties)
property.PublishCultureValues(languageId);
// 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));
property.PublishCultureValues(culture);
_publishedState = PublishedState.Publishing;
return true;
@@ -339,42 +401,42 @@ namespace Umbraco.Core.Models
// Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations.
ClearPublishNames();
ClearPublishNames();
_publishedState = PublishedState.Publishing;
}
/// <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
ContentType.ValidateVariation(languageId, segment, throwIfInvalid: true);
ContentType.ValidateVariation(culture, segment, throwIfInvalid: true);
// property.ClearPublishedValue throws on invalid variation, so filter them out
foreach (var property in Properties.Where(x => x.PropertyType.ValidateVariation(languageId, segment, throwIfInvalid: false)))
property.ClearPublishedValue(languageId, segment);
foreach (var property in Properties.Where(x => x.PropertyType.ValidateVariation(culture, segment, throwIfInvalid: false)))
property.ClearPublishedValue(culture, segment);
// Name and PublishName are managed by the repository, but Names and PublishNames
// must be managed here as they depend on the existing / supported variations.
ClearPublishName(languageId);
ClearPublishName(culture);
_publishedState = PublishedState.Publishing;
}
/// <inheritdoc />
public virtual void ClearCulturePublishedValues(int? languageId = null)
public virtual void ClearCulturePublishedValues(string culture = null)
{
// property.ClearPublishedCultureValues only deals with supported variations (if any)
foreach (var property in Properties)
property.ClearPublishedCultureValues(languageId);
property.ClearPublishedCultureValues(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.
ClearPublishName(languageId);
ClearPublishName(culture);
_publishedState = PublishedState.Publishing;
}
private bool CopyingFromSelf(IContent other)
{
// copying from the same Id and VersionPk
@@ -397,8 +459,8 @@ namespace Umbraco.Core.Models
// clear all existing properties
foreach (var property in Properties)
foreach (var pvalue in property.Values)
if (property.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false))
property.SetValue(null, pvalue.LanguageId, pvalue.Segment);
if (property.PropertyType.ValidateVariation(pvalue.Culture, pvalue.Segment, false))
property.SetValue(null, pvalue.Culture, pvalue.Segment);
// copy other properties
var otherProperties = other.Properties;
@@ -407,22 +469,22 @@ namespace Umbraco.Core.Models
var alias = otherProperty.PropertyType.Alias;
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;
var value = published ? pvalue.PublishedValue : pvalue.EditedValue;
SetValue(alias, value, pvalue.LanguageId, pvalue.Segment);
SetValue(alias, value, pvalue.Culture, pvalue.Segment);
}
}
}
// copy names
ClearNames();
ClearNames();
foreach (var (languageId, name) in other.Names)
SetName(languageId, name);
Name = other.Name;
}
/// <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)
throw new InvalidOperationException("Cannot copy values from a different content type.");
@@ -437,31 +499,31 @@ namespace Umbraco.Core.Models
// clear all existing properties
foreach (var property in Properties)
{
if (!property.PropertyType.ValidateVariation(languageId, segment, false))
if (!property.PropertyType.ValidateVariation(culture, segment, false))
continue;
foreach (var pvalue in property.Values)
if (pvalue.LanguageId == languageId && pvalue.Segment == segment)
property.SetValue(null, pvalue.LanguageId, pvalue.Segment);
if (pvalue.Culture.InvariantEquals(culture) && pvalue.Segment.InvariantEquals(segment))
property.SetValue(null, pvalue.Culture, pvalue.Segment);
}
// copy other properties
var otherProperties = other.Properties;
foreach (var otherProperty in otherProperties)
{
if (!otherProperty.PropertyType.ValidateVariation(languageId, segment, false))
if (!otherProperty.PropertyType.ValidateVariation(culture, segment, false))
continue;
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
SetName(languageId, other.GetName(languageId));
// copy name
SetName(culture, other.GetName(culture));
}
/// <inheritdoc />
public virtual void CopyCultureValues(IContent other, int? languageId = null)
public virtual void CopyCultureValues(IContent other, string culture = null)
{
if (other.ContentTypeId != ContentTypeId)
throw new InvalidOperationException("Cannot copy values from a different content type.");
@@ -473,8 +535,8 @@ namespace Umbraco.Core.Models
// clear all existing properties
foreach (var property in Properties)
foreach (var pvalue in property.Values)
if (pvalue.LanguageId == languageId && property.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false))
property.SetValue(null, pvalue.LanguageId, pvalue.Segment);
if (pvalue.Culture.InvariantEquals(culture) && property.PropertyType.ValidateVariation(pvalue.Culture, pvalue.Segment, false))
property.SetValue(null, pvalue.Culture, pvalue.Segment);
// copy other properties
var otherProperties = other.Properties;
@@ -483,15 +545,15 @@ namespace Umbraco.Core.Models
var alias = otherProperty.PropertyType.Alias;
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;
var value = published ? pvalue.PublishedValue : pvalue.EditedValue;
SetValue(alias, value, pvalue.LanguageId, pvalue.Segment);
SetValue(alias, value, pvalue.Culture, pvalue.Segment);
}
}
// copy name
SetName(languageId, other.GetName(languageId));
}
// copy name
SetName(culture, other.GetName(culture));
}
/// <summary>
+98 -89
View File
@@ -18,20 +18,20 @@ namespace Umbraco.Core.Models
[DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")]
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 int _contentTypeId;
protected IContentTypeComposition ContentTypeBase;
private int _writerId;
private PropertyCollection _properties;
private Dictionary<int, string> _names;
private Dictionary<string, string> _names;
/// <summary>
/// Initializes a new instance of the <see cref="ContentBase"/> class.
/// </summary>
protected ContentBase(string name, int parentId, IContentTypeComposition contentType, PropertyCollection properties)
: this(name, contentType, properties)
protected ContentBase(string name, int parentId, IContentTypeComposition contentType, PropertyCollection properties, string culture = null)
: this(name, contentType, properties, culture)
{
if (parentId == 0) throw new ArgumentOutOfRangeException(nameof(parentId));
ParentId = parentId;
@@ -40,22 +40,23 @@ namespace Umbraco.Core.Models
/// <summary>
/// Initializes a new instance of the <see cref="ContentBase"/> class.
/// </summary>
protected ContentBase(string name, IContentBase parent, IContentTypeComposition contentType, PropertyCollection properties)
: this(name, contentType, properties)
protected ContentBase(string name, IContentBase parent, IContentTypeComposition contentType, PropertyCollection properties, string culture = null)
: this(name, contentType, properties, culture)
{
if (parent == null) throw new ArgumentNullException(nameof(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));
// initially, all new instances have
Id = 0; // no identity
VersionId = 0; // no versions
SetName(culture, name);
Name = name;
_contentTypeId = contentType.Id;
_properties = properties ?? throw new ArgumentNullException(nameof(properties));
_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 PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
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)
@@ -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>
/// Gets the enumeration of property groups for the entity.
/// fixme is a proxy, kill this
@@ -199,6 +135,79 @@ namespace Umbraco.Core.Models
/// </summary>
[IgnoreDataMember]
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
@@ -207,29 +216,29 @@ namespace Umbraco.Core.Models
=> Properties.Contains(propertyTypeAlias);
/// <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)
? property.GetValue(languageId, segment, published)
? property.GetValue(culture, segment, published)
: null;
}
/// <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))
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;
}
/// <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))
{
Properties[propertyTypeAlias].SetValue(value, languageId, segment);
Properties[propertyTypeAlias].SetValue(value, culture, segment);
return;
}
@@ -238,7 +247,7 @@ namespace Umbraco.Core.Models
throw new InvalidOperationException($"No PropertyType exists with the supplied alias \"{propertyTypeAlias}\".");
var property = propertyType.CreateProperty();
property.SetValue(value, languageId, segment);
property.SetValue(value, culture, segment);
Properties.Add(property);
}
@@ -249,17 +258,17 @@ namespace Umbraco.Core.Models
/// <summary>
/// Sets the posted file value of a property.
/// </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>
/// Sets the posted file value of a property.
/// </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
@@ -271,14 +280,14 @@ namespace Umbraco.Core.Models
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
+5 -18
View File
@@ -159,20 +159,7 @@ namespace Umbraco.Core.Models
return Current.Services.MediaService.GetById(media.ParentId);
}
#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>
/// Removes characters that are not valide XML characters from all entity properties
/// of type string. See: http://stackoverflow.com/a/961504/5018
@@ -284,7 +271,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Sets the posted file value of a property.
/// </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
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
@@ -303,7 +290,7 @@ namespace Umbraco.Core.Models
if (string.IsNullOrWhiteSpace(filename)) return;
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>
@@ -312,7 +299,7 @@ namespace Umbraco.Core.Models
/// <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
/// 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;
@@ -321,7 +308,7 @@ namespace Umbraco.Core.Models
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, languageId, segment);
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
}
/// <summary>
+3 -3
View File
@@ -204,10 +204,10 @@ namespace Umbraco.Core.Models
/// <summary>
/// Validates that a variation is valid for the content type.
/// </summary>
public bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid)
public bool ValidateVariation(string culture, string segment, bool throwIfInvalid)
{
ContentVariation variation;
if (languageId.HasValue)
if (culture != null)
{
variation = segment != null
? ContentVariation.CultureSegment
@@ -221,7 +221,7 @@ namespace Umbraco.Core.Models
{
variation = ContentVariation.InvariantNeutral;
}
if ((Variations & variation) == 0)
if (!Variations.Has(variation))
{
if (throwIfInvalid)
throw new NotSupportedException($"Variation {variation} is invalid for content type \"{Alias}\".");
+1 -7
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)
/// </summary>
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,
// can implement their own cloning - (though really, not sure it's even needed)
protected virtual void DeepCloneNameAndAlias(File clone)
+43 -21
View File
@@ -59,7 +59,7 @@ namespace Umbraco.Core.Models
/// Gets the date and time the content was published.
/// </summary>
DateTime? PublishDate { get; }
/// <summary>
/// Gets or sets the date and time the content item should be published.
/// </summary>
@@ -80,15 +80,6 @@ namespace Umbraco.Core.Models
/// </summary>
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>
/// Gets a value indicating whether a given culture is published.
/// </summary>
@@ -97,17 +88,31 @@ namespace Umbraco.Core.Models
/// and the content published name for this culture is non-null. It becomes non-published
/// whenever values for this culture are unpublished.</para>
/// </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>
/// Gets the name of the published version of the content for a given culture.
/// </summary>
/// <remarks>
/// <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>
/// </remarks>
string GetPublishName(int? languageId);
string GetPublishName(string culture);
/// <summary>
/// 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
/// name, which must be get via the <see cref="PublishName"/> property.</para>
/// </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
@@ -149,7 +169,8 @@ namespace Umbraco.Core.Models
/// <para>The document must then be published via the content service.</para>
/// <para>Values are not published if they are not valie.</para>
/// </remarks>
bool PublishAllValues();
//fixme return an Attempt with some error results if it doesn't work
bool TryPublishAllValues();
/// <summary>
/// Publishes values.
@@ -159,7 +180,8 @@ namespace Umbraco.Core.Models
/// <para>The document must then be published via the content service.</para>
/// <para>Values are not published if they are not valid.</para>
/// </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>
/// 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>Values are not published if they are not valie.</para>
/// </remarks>
bool PublishCultureValues(int? languageId = null);
bool PublishCultureValues(string culture = null);
/// <summary>
/// Clears all published values.
@@ -179,12 +201,12 @@ namespace Umbraco.Core.Models
/// <summary>
/// Clears published values.
/// </summary>
void ClearPublishedValues(int? languageId = null, string segment = null);
void ClearPublishedValues(string culture = null, string segment = null);
/// <summary>
/// Clears the culture/any published values.
/// </summary>
void ClearCulturePublishedValues(int? languageId = null);
void ClearCulturePublishedValues(string culture = null);
/// <summary>
/// Copies values from another document.
@@ -194,11 +216,11 @@ namespace Umbraco.Core.Models
/// <summary>
/// Copies values from another document.
/// </summary>
void CopyValues(IContent other, int? languageId = null, string segment = null);
void CopyValues(IContent other, string culture = null, string segment = null);
/// <summary>
/// Copies culture/any values from another document.
/// </summary>
void CopyCultureValues(IContent other, int? languageId = null);
void CopyCultureValues(IContent other, string culture = null);
}
}
+20 -11
View File
@@ -31,19 +31,19 @@ namespace Umbraco.Core.Models
/// Sets the name of the content item for a specified language.
/// </summary>
/// <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>
/// </remarks>
void SetName(int? languageId, string value);
void SetName(string culture, string value);
/// <summary>
/// Gets the name of the content item for a specified language.
/// </summary>
/// <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>
/// </remarks>
string GetName(int? languageId);
string GetName(string culture);
/// <summary>
/// Gets or sets the names of the content item.
@@ -51,9 +51,18 @@ namespace Umbraco.Core.Models
/// <remarks>
/// <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>
/// </remarks>
IReadOnlyDictionary<int, string> Names { get; set; }
/// </remarks>
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>
/// List of properties, which make up all the data available for this Content object
/// </summary>
@@ -82,17 +91,17 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets the value of a Property
/// </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>
/// Gets the typed value of a Property
/// </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>
/// Sets the (edited) value of a Property
/// </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>
/// Gets a value indicating whether the content and all its properties values are valid.
@@ -102,11 +111,11 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets a value indicating whether the content and its properties values are valid.
/// </summary>
Property[] Validate(int? languageId = null, string segment = null);
Property[] Validate(string culture = null, string segment = null);
/// <summary>
/// Gets a value indicating whether the content and its culture/any properties values are valid.
/// </summary>
Property[] ValidateCulture(int? languageId = null);
Property[] ValidateCulture(string culture = null);
}
}
+1 -1
View File
@@ -51,7 +51,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Validates that a variation is valid for the content type.
/// </summary>
bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid);
bool ValidateVariation(string culture, string segment, bool throwIfInvalid);
/// <summary>
/// Gets or Sets a list of integer Ids of the ContentTypes allowed under the ContentType
+1 -3
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)
/// </summary>
string VirtualPath { get; set; }
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
bool IsValid();
}
}
+7 -23
View File
@@ -51,35 +51,19 @@ namespace Umbraco.Core.Models
/// </summary>
[DataMember]
bool DontRender { get; set; }
/// <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>
[DataMember]
string ControlType { get; set; }
string MacroSource { get; set; }
/// <summary>
/// Gets or sets the name of the assembly, which should be used by the Macro
/// Gets or set the macro type
/// </summary>
/// <remarks>Will usually only be filled if the ScriptFile is a Usercontrol</remarks>
[DataMember]
[Obsolete("This is no longer used, we should remove it in v8, CustomControl macros are gone")]
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; }
MacroTypes MacroType { get; set; }
/// <summary>
/// Gets or sets a list of Macro Properties
/// </summary>
-7
View File
@@ -1,7 +0,0 @@
namespace Umbraco.Core.Models
{
public interface IXsltFile : IFile
{
}
}
+23 -62
View File
@@ -34,14 +34,11 @@ namespace Umbraco.Core.Models
/// <param name="cacheDuration"></param>
/// <param name="alias"></param>
/// <param name="name"></param>
/// <param name="controlType"></param>
/// <param name="controlAssembly"></param>
/// <param name="xsltPath"></param>
/// <param name="cacheByPage"></param>
/// <param name="cacheByMember"></param>
/// <param name="dontRender"></param>
/// <param name="scriptPath"></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)
/// <param name="macroSource"></param>
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()
{
Id = id;
@@ -50,13 +47,11 @@ namespace Umbraco.Core.Models
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name;
ControlType = controlType;
ControlAssembly = controlAssembly;
XsltPath = xsltPath;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
ScriptPath = scriptPath;
MacroSource = macroSource;
MacroType = macroType;
}
/// <summary>
@@ -66,18 +61,13 @@ namespace Umbraco.Core.Models
/// <param name="cacheDuration"></param>
/// <param name="alias"></param>
/// <param name="name"></param>
/// <param name="controlType"></param>
/// <param name="controlAssembly"></param>
/// <param name="xsltPath"></param>
/// <param name="cacheByPage"></param>
/// <param name="cacheByMember"></param>
/// <param name="dontRender"></param>
/// <param name="scriptPath"></param>
/// <param name="macroSource"></param>
public Macro(string @alias, string name,
string controlType = "",
string controlAssembly = "",
string xsltPath = "",
string scriptPath = "",
string macroSource,
MacroTypes macroType,
bool cacheByPage = false,
bool cacheByMember = false,
bool dontRender = true,
@@ -89,13 +79,11 @@ namespace Umbraco.Core.Models
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name;
ControlType = controlType;
ControlAssembly = controlAssembly;
XsltPath = xsltPath;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
ScriptPath = scriptPath;
MacroSource = macroSource;
MacroType = macroType;
}
private string _alias;
@@ -105,10 +93,8 @@ namespace Umbraco.Core.Models
private bool _cacheByPage;
private bool _cacheByMember;
private bool _dontRender;
private string _scriptFile;
private string _scriptAssembly;
private string _scriptPath;
private string _xslt;
private string _macroSource;
private MacroTypes _macroType = MacroTypes.Unknown;
private MacroPropertyCollection _properties;
private List<string> _addedProperties;
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 CacheByMemberSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByMember);
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 ControlAssemblySelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlAssembly);
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 ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.MacroSource);
public readonly PropertyInfo MacroTypeSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroTypes>(x => x.MacroType);
public readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroPropertyCollection>(x => x.Properties);
}
@@ -272,46 +256,23 @@ namespace Umbraco.Core.Models
}
/// <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>
[DataMember]
public string ControlType
public string MacroSource
{
get { return _scriptFile; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptFile, Ps.Value.ControlPathSelector); }
}
get { return _macroSource; }
set { SetPropertyValueAndDetectChanges(value, ref _macroSource, Ps.Value.ScriptPathSelector); }
}
/// <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>
/// <remarks>Will usually only be filled if the ControlType is a Usercontrol</remarks>
[DataMember]
public string ControlAssembly
public MacroTypes MacroType
{
get { return _scriptAssembly; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptAssembly, Ps.Value.ControlAssemblySelector); }
}
/// <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); }
get { return _macroType; }
set { SetPropertyValueAndDetectChanges(value, ref _macroType, Ps.Value.MacroTypeSelector); }
}
/// <summary>
-4
View File
@@ -10,15 +10,11 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public enum MacroTypes
{
[EnumMember]
Xslt = 1,
[EnumMember]
UserControl = 3,
[EnumMember]
Unknown = 4,
[EnumMember]
Script = 6,
[EnumMember]
PartialView = 7
}
}
+1 -1
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
/// </summary>
/// <returns></returns>
public IMediaType DeepCloneWithResetIdentities(string alias)
public new IMediaType DeepCloneWithResetIdentities(string alias)
{
var clone = (MediaType)DeepClone();
clone.Alias = alias;
+2 -14
View File
@@ -18,11 +18,7 @@ namespace Umbraco.Core.Models.Membership
int[] StartContentIds { get; set; }
int[] StartMediaIds { 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? InvitedDate { get; set; }
@@ -37,14 +33,6 @@ namespace Umbraco.Core.Models.Membership
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>
/// Exposes the basic profile data
/// </summary>
@@ -65,4 +53,4 @@ namespace Umbraco.Core.Models.Membership
/// </summary>
string TourData { get; set; }
}
}
}
@@ -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; }
}
}
-156
View File
@@ -284,162 +284,6 @@ namespace Umbraco.Core.Models.Membership
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>
/// This used purely for hacking backwards compatibility into this class for &lt; 7.7 compat
/// </summary>
@@ -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()));
}
}
}
}
+48 -43
View File
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models
{
private List<PropertyValue> _values = new List<PropertyValue>();
private PropertyValue _pvalue;
private Dictionary<CompositeIntStringKey, PropertyValue> _vvalues;
private Dictionary<CompositeStringStringKey, PropertyValue> _vvalues;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
@@ -38,9 +38,14 @@ namespace Umbraco.Core.Models
public class PropertyValue
{
private string _culture;
private string _segment;
public int? LanguageId { get; internal set; }
public string Culture
{
get => _culture;
internal set => _culture = value?.ToLowerInvariant();
}
public string Segment
{
get => _segment;
@@ -50,7 +55,7 @@ namespace Umbraco.Core.Models
public object PublishedValue { get; internal set; }
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
@@ -96,10 +101,10 @@ namespace Umbraco.Core.Models
{
// make sure we filter out invalid variations
// make sure we leave _vvalues null if possible
_values = value.Where(x => PropertyType.ValidateVariation(x.LanguageId, x.Segment, false)).ToList();
_pvalue = _values.FirstOrDefault(x => !x.LanguageId.HasValue && x.Segment == null);
_values = value.Where(x => PropertyType.ValidateVariation(x.Culture, x.Segment, false)).ToList();
_pvalue = _values.FirstOrDefault(x => x.Culture == null && x.Segment == null);
_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;
}
}
@@ -128,12 +133,12 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets the value.
/// </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 (!languageId.HasValue && segment == null) return GetPropertyValue(_pvalue, published);
if (!PropertyType.ValidateVariation(culture, segment, false)) return null;
if (culture == null && segment == null) return GetPropertyValue(_pvalue, published);
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)
: null;
}
@@ -159,7 +164,7 @@ namespace Umbraco.Core.Models
if (_vvalues != null)
{
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);
foreach (var pvalue in pvalues)
PublishPropertyValue(pvalue);
@@ -168,29 +173,29 @@ namespace Umbraco.Core.Models
// internal - must be invoked by the content item
// 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;
PublishPropertyValue(pvalue);
}
// internal - must be invoked by the content item
// 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 (!languageId.HasValue && PropertyType.ValidateVariation(null, null, false))
if (culture == null && PropertyType.ValidateVariation(null, null, false))
PublishPropertyValue(_pvalue);
// publish everything not invariant-neutral that matches the culture and is supported
if (_vvalues != null)
{
var pvalues = _vvalues
.Where(x => x.Value.LanguageId == languageId)
.Where(x => PropertyType.ValidateVariation(languageId, x.Value.Segment, false))
.Where(x => x.Value.Culture.InvariantEquals(culture))
.Where(x => PropertyType.ValidateVariation(culture, x.Value.Segment, false))
.Select(x => x.Value);
foreach (var pvalue in pvalues)
PublishPropertyValue(pvalue);
@@ -206,7 +211,7 @@ namespace Umbraco.Core.Models
if (_vvalues != null)
{
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);
foreach (var pvalue in pvalues)
ClearPublishedPropertyValue(pvalue);
@@ -214,25 +219,25 @@ namespace Umbraco.Core.Models
}
// 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);
(var pvalue, _) = GetPValue(languageId, segment, false);
PropertyType.ValidateVariation(culture, segment, true);
(var pvalue, _) = GetPValue(culture, segment, false);
if (pvalue == null) return;
ClearPublishedPropertyValue(pvalue);
}
// 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);
if (_vvalues != null)
{
var pvalues = _vvalues
.Where(x => x.Value.LanguageId == languageId)
.Where(x => PropertyType.ValidateVariation(languageId, x.Value.Segment, false))
.Where(x => x.Value.Culture.InvariantEquals(culture))
.Where(x => PropertyType.ValidateVariation(culture, x.Value.Segment, false))
.Select(x => x.Value);
foreach (var pvalue in pvalues)
ClearPublishedPropertyValue(pvalue);
@@ -264,10 +269,10 @@ namespace Umbraco.Core.Models
/// <summary>
/// Sets a value.
/// </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);
(var pvalue, var change) = GetPValue(languageId, segment, true);
PropertyType.ValidateVariation(culture, segment, true);
(var pvalue, var change) = GetPValue(culture, segment, true);
var origValue = pvalue.EditedValue;
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
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)
pvalue.PublishedValue = value;
@@ -301,24 +306,24 @@ namespace Umbraco.Core.Models
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);
var change = false;
if (_vvalues == null)
{
if (!create) return (null, false);
_vvalues = new Dictionary<CompositeIntStringKey, PropertyValue>();
_vvalues = new Dictionary<CompositeStringStringKey, PropertyValue>();
change = true;
}
var k = new CompositeIntStringKey(languageId, segment);
var k = new CompositeStringStringKey(culture, segment);
if (!_vvalues.TryGetValue(k, out var pvalue))
{
if (!create) return (null, false);
pvalue = _vvalues[k] = new PropertyValue();
pvalue.LanguageId = languageId;
pvalue.Culture = culture;
pvalue.Segment = segment;
_values.Add(pvalue);
change = true;
@@ -343,7 +348,7 @@ namespace Umbraco.Core.Models
if (_vvalues == null) return true;
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)
.ToArray();
@@ -354,11 +359,11 @@ namespace Umbraco.Core.Models
/// Gets a value indicating whether the culture/any values are valid.
/// </summary>
/// <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
// includes mandatory validation
if (PropertyType.ValidateVariation(languageId, null, false) && !IsValidValue(GetValue(languageId)))
if (PropertyType.ValidateVariation(culture, null, false) && !IsValidValue(GetValue(culture)))
return false;
// either culture-neutral is not supported, or it is valid
@@ -368,8 +373,8 @@ namespace Umbraco.Core.Models
if (_vvalues == null) return true;
var pvalues = _vvalues
.Where(x => x.Value.LanguageId == languageId)
.Where(x => PropertyType.ValidateVariation(languageId, x.Value.Segment, false))
.Where(x => x.Value.Culture.InvariantEquals(culture))
.Where(x => PropertyType.ValidateVariation(culture, x.Value.Segment, false))
.Select(x => x.Value)
.ToArray();
@@ -380,10 +385,10 @@ namespace Umbraco.Core.Models
/// Gets a value indicating whether the value is valid.
/// </summary>
/// <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
return IsValidValue(GetValue(languageId, segment));
return IsValidValue(GetValue(culture, segment));
}
/// <summary>
@@ -67,8 +67,10 @@ namespace Umbraco.Core.Models
internal new void Add(PropertyGroup item)
{
using (new WriteLock(_addLocker))
try
{
_addLocker.EnterWriteLock();
//Note this is done to ensure existig groups can be renamed
if (item.HasIdentity && item.Id > 0)
{
@@ -102,6 +104,11 @@ namespace Umbraco.Core.Models
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
finally
{
if (_addLocker.IsWriteLockHeld)
_addLocker.ExitWriteLock();
}
}
/// <summary>
+3 -3
View File
@@ -226,10 +226,10 @@ namespace Umbraco.Core.Models
/// <summary>
/// Validates that a variation is valid for the property type.
/// </summary>
public bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid)
public bool ValidateVariation(string culture, string segment, bool throwIfInvalid)
{
ContentVariation variation;
if (languageId.HasValue)
if (culture != null)
{
variation = segment != null
? ContentVariation.CultureSegment
@@ -243,7 +243,7 @@ namespace Umbraco.Core.Models
{
variation = ContentVariation.InvariantNeutral;
}
if ((Variations & variation) == 0)
if (!Variations.Has(variation))
{
if (throwIfInvalid)
throw new NotSupportedException($"Variation {variation} is invalid for property type \"{Alias}\".");
@@ -80,8 +80,9 @@ namespace Umbraco.Core.Models
item.IsPublishing = IsPublishing;
// fixme redo this entirely!!!
using (new WriteLock(_addLocker))
try
{
_addLocker.EnterWriteLock();
var key = GetKeyForItem(item);
if (key != null)
{
@@ -105,6 +106,11 @@ namespace Umbraco.Core.Models
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
finally
{
if (_addLocker.IsWriteLockHeld)
_addLocker.ExitWriteLock();
}
}
/// <summary>
@@ -3,17 +3,11 @@ using System.Collections.Generic;
namespace Umbraco.Core.Models.PublishedContent
{
/// <inheritdoc />
/// <summary>
/// Represents a cached content.
/// </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
{
#region Content
@@ -38,6 +32,8 @@ namespace Umbraco.Core.Models.PublishedContent
int Level { get; }
string Url { get; }
IReadOnlyDictionary<string, PublishedCultureName> CultureNames { get; }
/// <summary>
/// Gets a value indicating whether the content is a content (aka a document) or a media.
/// </summary>
@@ -21,7 +21,7 @@
/// <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>
/// </remarks>
bool HasValue(int? languageId = null, string segment = null);
bool HasValue(string culture = null, string segment = null);
/// <summary>
/// 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
/// Umbraco stuff.</para>
/// </remarks>
object GetSourceValue(int? languageId = null, string segment = null);
object GetSourceValue(string culture = null, string segment = null);
/// <summary>
/// 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 has been fully prepared and processed by the appropriate converter.</para>
/// </remarks>
object GetValue(int? languageId = null, string segment = null);
object GetValue(string culture = null, string segment = null);
/// <summary>
/// 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 has been fully prepared and processed by the appropriate converter.</para>
/// </remarks>
object GetXPathValue(int? languageId = null, string segment = null);
object GetXPathValue(string culture = null, string segment = null);
}
}
@@ -54,7 +54,9 @@ namespace Umbraco.Core.Models.PublishedContent
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;
@@ -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; }
}
}
@@ -53,15 +53,15 @@ namespace Umbraco.Core.Models.PublishedContent
public string Alias => PropertyType.Alias;
/// <inheritdoc />
public abstract bool HasValue(int? languageId = null, string segment = null);
public abstract bool HasValue(string culture = null, string segment = null);
/// <inheritdoc />
public abstract object GetSourceValue(int? languageId = null, string segment = null);
public abstract object GetSourceValue(string culture = null, string segment = null);
/// <inheritdoc />
public abstract object GetValue(int? languageId = null, string segment = null);
public abstract object GetValue(string culture = null, string segment = null);
/// <inheritdoc />
public abstract object GetXPathValue(int? languageId = null, string segment = null);
public abstract object GetXPathValue(string culture = null, string segment = null);
}
}
@@ -20,20 +20,20 @@ namespace Umbraco.Core.Models.PublishedContent
private readonly Lazy<object> _objectValue;
private readonly Lazy<object> _xpathValue;
public override object GetSourceValue(int? languageId = null, string segment = null)
=> languageId == null & segment == null ? _sourceValue : null;
public override object GetSourceValue(string culture = null, string segment = 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;
}
public override object GetValue(int? languageId = null, string segment = null)
=> languageId == null & segment == null ? _objectValue.Value : null;
public override object GetValue(string culture = null, string segment = null)
=> culture == null & segment == null ? _objectValue.Value : null;
public override object GetXPathValue(int? languageId = null, string segment = null)
=> languageId == null & segment == null ? _xpathValue.Value : null;
public override object GetXPathValue(string culture = null, string segment = null)
=> culture == null & segment == null ? _xpathValue.Value : null;
public RawValueProperty(PublishedPropertyType propertyType, IPublishedElement content, object sourceValue, bool isPreviewing = false)
: base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored
+1 -19
View File
@@ -14,14 +14,6 @@ namespace Umbraco.Core.Models
/// </summary>
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>
/// Root
@@ -69,17 +61,7 @@ namespace Umbraco.Core.Models
[FriendlyName("Member Group")]
[UmbracoUdiType(Constants.UdiEntityType.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>
/// "Media Type
/// </summary>
@@ -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>
/// Returns the culture info associated with this user, based on the language they're assigned to in the back office
/// </summary>
-32
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; }
}
}
}
@@ -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; }
}
}
}
@@ -1,11 +0,0 @@
using NuGet;
namespace Umbraco.Core.Packaging
{
internal interface IPackageContext
{
IPackageManager LocalPackageManager { get; }
IPackageManager PublicPackageManager { get; }
IPackagePathResolver LocalPathResolver { get; }
}
}
@@ -17,10 +17,10 @@ namespace Umbraco.Core
public const string NodeXml = /*TableNamePrefix*/ "cms" + "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 DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme dbfixmust rename corresponding DTO
public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme dbfixwhy can't we just use uNode for this?
public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme dbfix must rename corresponding DTO
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 Template = /*TableNamePrefix*/ "cms" + "Template";
@@ -28,6 +28,7 @@ namespace Umbraco.Core
public const string ContentVersion = TableNamePrefix + "ContentVersion";
public const string ContentVersionCultureVariation = TableNamePrefix + "ContentVersionCultureVariation";
public const string Document = TableNamePrefix + "Document";
public const string DocumentCultureVariation = TableNamePrefix + "DocumentCultureVariation";
public const string DocumentVersion = TableNamePrefix + "DocumentVersion";
public const string MediaVersion = TableNamePrefix + "MediaVersion";
@@ -16,6 +16,12 @@ namespace Umbraco.Core.Persistence.Dtos
[Column("published")]
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")]
[SpecialDbType(SpecialDbTypes.NTEXT)]
public string Data { get; set; }
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Dtos
[ExplicitColumns]
internal class ContentVersionCultureVariationDto
{
private const string TableName = Constants.DatabaseSchema.Tables.ContentVersionCultureVariation;
public const string TableName = Constants.DatabaseSchema.Tables.ContentVersionCultureVariation;
[Column("id")]
[PrimaryKeyColumn]
@@ -25,21 +25,21 @@ namespace Umbraco.Core.Persistence.Dtos
[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("name")]
[NullSetting(NullSetting = NullSettings.Null)]
public string Name { get; set; }
[Column("available")]
public bool Available { get; set; }
[Column("availableDate")]
[NullSetting(NullSetting = NullSettings.Null)]
public DateTime? AvailableDate { get; set; }
[Column("date")]
public DateTime Date { get; set; }
// fixme want?
[Column("availableUserId")]
// [ForeignKey(typeof(UserDto))] -- there is no foreign key so we can delete users without deleting associated content
//[NullSetting(NullSetting = NullSettings.Null)]
public int AvailableUserId { get; set; }
public int PublishedUserId { get; set; }
[Column("edited")]
public bool Edited { get; set; }
@@ -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; }
}
}
+7 -16
View File
@@ -34,18 +34,6 @@ namespace Umbraco.Core.Persistence.Dtos
[NullSetting(NullSetting = NullSettings.Null)]
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")]
[Constraint(Default = "1")]
public bool CacheByPage { get; set; }
@@ -58,10 +46,13 @@ namespace Umbraco.Core.Persistence.Dtos
[Constraint(Default = "0")]
public bool DontRender { get; set; }
//TODO: Rename this column! - actually please revamp all of the macros! :)
[Column("macroPython")]
[NullSetting(NullSetting = NullSettings.Null)]
public string MacroFilePath { get; set; }
[Column("macroSource")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public string MacroSource { get; set; }
[Column("macroType")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int MacroType { get; set; }
[ResultColumn]
[Reference(ReferenceType.Many, ReferenceMemberName = "Macro")]

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