Compare commits

..

74 Commits

Author SHA1 Message Date
Sebastiaan Janssen a91669abc0 Fixes unit tests 2016-02-17 13:28:11 +01:00
Shannon 3b9db8a92f tries fixing test for appveyor 2016-02-17 12:25:40 +01:00
Sebastiaan Janssen 1bfc1229bd Merge pull request #1134 from umbraco/temp-738-U4-7996
Upgrade SQL CE to hopefully fix SQL CE data loss bug
2016-02-17 11:54:25 +01:00
Sebastiaan Janssen 3d6fd2d785 Updates to SQL CE 4.0.0.1 2016-02-17 11:44:33 +01:00
Shannon e56881abc6 adds unit tests for new ext methods 2016-02-17 11:21:15 +01:00
Shannon d32991c30a re-organizing some namespaces for tests 2016-02-17 10:59:48 +01:00
Shannon 8758f9649b checks for null before assigning culture 2016-02-17 10:57:20 +01:00
Shannon 6f0f1ab2c3 fixes wrong constant used 2016-02-17 10:22:37 +01:00
Shannon cd28240172 Moves strings to constants, adds ControllerContextExtensions to get the UmbracoContext from the hierarchy of ControllerContext's, changes RenderModelBinder to use this method to get the UmbracoContext, changes UmbracoViewPageOfTModel to use this method to get the UmbracoContext, adds RouteDataExtensions to get the UmbracoContext from routedata, adds extension methods on the HttpContext to get the UmbracoContext from it.
Conflicts:
	src/Umbraco.Web/Mvc/RenderModelBinder.cs
2016-02-17 10:22:22 +01:00
Shannon 7002291c41 adds tests for ShouldAuthenticateRequest for app configurations 2016-02-16 14:51:15 +01:00
Shannon 51bbf7ceb5 U4-7494 Installation Fails for 7.3.3 - Intermittent - Value cannot be null. Parameter name: sqlSyntax 2016-02-16 14:22:59 +01:00
Shannon 82297a6ff1 U4-7929 Label datatype strips leading zeros 2016-02-16 13:23:37 +01:00
Shannon cc5ac1a84c bumps version 2016-02-16 11:57:10 +01:00
Shannon 6373add383 U4-7922 Preview is not working 2016-02-16 11:53:54 +01:00
Shannon 180099b718 U4-7890 XSLT Macro's not working - "Cannot use this obsoleted overload when the current provider" 2016-02-16 11:52:16 +01:00
Shannon 65f15125e1 U4-7939 - fix routes cache 2016-02-16 11:48:09 +01:00
Shannon 856c345905 Merge branch '7.3.7' of https://github.com/umbraco/Umbraco-CMS into 7.3.7 2016-02-02 18:01:56 +01:00
Shannon b2cd5dfb85 adds null check to session id - might not exist in old cookies 2016-02-02 18:01:36 +01:00
Sebastiaan Janssen 462f7a59b5 Merge pull request #1078 from dawoe/U4-7872
Use product name in migration runner instead of Umbraco productname
2016-02-02 17:06:56 +01:00
Shannon 22689d24ec changes port 2016-02-02 17:05:21 +01:00
Shannon 4055afdf05 Merge branch '7.3.7' of https://github.com/umbraco/Umbraco-CMS into 7.3.7 2016-02-02 16:52:08 +01:00
Shannon a1c70a219a ensures correct sort order for content type queries + test 2016-02-02 16:51:57 +01:00
Sebastiaan Janssen 3151515855 U4-7072 Grid TinyMce with style_formats throws "Cannot assign to read only property 'name' 2016-02-02 16:09:02 +01:00
Shannon 25df9da715 bumps Version 2016-02-02 16:00:28 +01:00
Shannon 9c2f438476 fixes tests 2016-02-02 15:43:44 +01:00
Shannon 0de3be42cf U4-7869 Examine & SQL Azure - Timeouts - ensure the other reader is executed with retry. 2016-02-02 15:33:22 +01:00
Shannon 1545e0eed7 Merge branch '7.3.7' of https://github.com/umbraco/Umbraco-CMS into 7.3.7 2016-02-02 15:14:56 +01:00
Shannon 42a7ed6877 U4-7821 KeepUserLoggedIn with a long umbracoTimeOutInMinutes has logout issues 2016-02-02 15:14:47 +01:00
Sebastiaan Janssen 98b8aedc4d U4-7849 Unclear error message when applying public access 2016-02-02 15:13:57 +01:00
Shannon c7a2b54d1c Merge branch '7.3.7' of https://github.com/umbraco/Umbraco-CMS into 7.3.7 2016-02-02 12:13:03 +01:00
Shannon 6583ff4439 U4-7821 KeepUserLoggedIn with a long umbracoTimeOutInMinutes has logout issues 2016-02-02 12:12:51 +01:00
Sebastiaan Janssen 7b08b3e936 Merged branch 7.3.7 into 7.3.7 2016-02-02 11:55:40 +01:00
Sebastiaan Janssen bd2fc71dc5 U4-7276 When creating folders in the "Partials" view folder a YSOD appears (Umbraco 7.3 and 7.4) 2016-02-02 11:55:24 +01:00
Shannon 0af97f63e2 U4-7857 Flexible Load Balancing does not sync with the correct timeout threshold 2016-02-02 11:11:47 +01:00
Shannon 1db635f24c Updates DeepCloneableList to support behaviors, for the FullDataSetCachePolicy we only want to clone when writing to cache, not when reading, the cloning will then be done on individual items after filtering by the FullDataSetRepositoryCachePolicy 2016-02-02 01:32:36 +01:00
Shannon 6e27b3d6d4 Fixes up the FullDataSetRepositoryCachePolicy to handle individual items, updates and removes correctly, splits up it's logic so it's not overriding the DefaultRepositoryCachePolicy since that is just different. Adds tests. 2016-02-02 00:47:18 +01:00
Shannon 1dea0edcf1 re-includes the static cache for published property types, this cache is much more than a simple cache of content type infos, it is also the cache for associated converters which is required for all front-end rendering. Fixes the issue of not setting the xpath cache level corectly. 2016-02-01 22:50:38 +01:00
Shannon 1abab41955 Fixes perf issue with DeepCloneHelper - so we cache the actual property types instead of re-reflecting each time 2016-02-01 21:45:34 +01:00
Shannon d1be38be64 reverts profiler changes, we'll inlcude in 7.4 2016-01-28 18:37:56 +01:00
Shannon 8916c68a0c reverts profiler changes, we'll inlcude in 7.4 2016-01-28 18:35:29 +01:00
Shannon 6faa7e2fc9 dont' have RebuildOnAppStart set for dev purposes! 2016-01-28 18:31:47 +01:00
Shannon a6093f41bd Fixes installer login for user and adds notes 2016-01-28 18:02:22 +01:00
Stephan 107e66e4da Merge pull request #1071 from umbraco/temp-U4-7682
U4-7682 Add option to DatabaseServerMessengerOptions to force a Cold …
2016-01-28 14:33:02 +01:00
Shannon 256849f8a6 adds nicer profiling during startup for app event handlers. 2016-01-28 14:19:38 +01:00
Stephan c9c451be65 U4-7682 Minor review adjustments 2016-01-28 14:19:32 +01:00
Shannon 1fcea083e7 Ensures no profiling occurs when not in debug mode 2016-01-28 14:10:13 +01:00
Shannon 85d6ee5713 Merge branch '7.3.6' of https://github.com/umbraco/Umbraco-CMS into 7.3.6 2016-01-28 13:50:55 +01:00
Shannon ec81583741 Fixes case sensitive matching on alias in TemplateRepository 2016-01-28 13:50:45 +01:00
Sebastiaan Janssen 332da9bf2d Merge pull request #1070 from umbraco/temp-RepoCachePerf736
Temp repo cache perf736
2016-01-28 12:15:24 +01:00
Shannon a0036d925e U4-7682 Add option to DatabaseServerMessengerOptions to force a Cold Boot if there are too many instructions 2016-01-28 12:14:30 +01:00
Shannon 81a99d6f7d adds null check and ensures that SetInternalRedirectPublishedContent cannot be called with a null result 2016-01-28 10:19:51 +01:00
Shannon e912238574 Saw there was another place with the incorrect case for the column name AllowedId 2016-01-28 09:32:01 +01:00
Shannon 9a830e5de6 fixes tests 2016-01-27 19:44:36 +01:00
Shannon 7d9ba0e36e manually backports changes from 7.4 fixes 2016-01-27 19:42:06 +01:00
Shannon 6c5e09fd84 Ensures that the main content type repositories are returning the correct result from their GetAll methods. Fixes the FullDataSetRepositoryCachePolicy to ensure that any request with Ids actually returns the result of GetAll and then filters to ensure caching is correct. 2016-01-27 19:26:08 +01:00
Sebastiaan Janssen 2f8c43c689 Merge pull request #1057 from umbraco/temp-U4-7836
U4-7836 YSOD when upgrading Umbraco with error during AddUserDataClaims
2016-01-26 19:25:04 +01:00
Shannon 7a25cb52b2 updates the repository cache policies so that we aren't keeping everything in cache unnecessarily 2016-01-26 19:13:42 +01:00
Shannon 19bc97a7fd Removes the static (hack) cache for content types for creating published content 2016-01-26 18:56:29 +01:00
Shannon 72900ef3b3 U4-7813 Enable MiniProfiler to profiler during startup
Conflicts:
	src/Umbraco.Core/Umbraco.Core.csproj
2016-01-26 17:56:25 +01:00
Shannon 74ddd09c5d U4-7836 YSOD when upgrading Umbraco with error during AddUserDataClaims - this also ensures that no empty/null sections can be added to the user object since this is where the original exception was coming from. 2016-01-26 17:05:46 +01:00
Sebastiaan Janssen e461cb92da U4-7787 Shorthand use of ?altTemplate= doesn't work
#U4-7787 Fixed
2016-01-26 16:07:44 +01:00
Mads Rasmussen e91b53e66d back ported: https://github.com/Umbraco/Umbraco-CMS/commit/2d0f198f58071f5113d5c3437f10f2b85220c348 2016-01-25 11:09:20 +01:00
Shannon b5e8cb29dd ensure appctx and security isn't nulled on disposal (it's an application singleton it doesn't need to be nulled), creates new CreateContext method for creating standalone UmbracoContext instances. 2016-01-23 12:38:08 +01:00
Shannon 20dc4f5bc4 fixes merge issue/build 2016-01-23 12:27:40 +01:00
Shannon 2c399860ca Fixes DisposableTimer so that the profiled step is disposed - and thus tracked/timed properly! 2016-01-22 17:27:46 +01:00
Shannon 4dc4c36581 U4-7811 Content type repositories should use FullDataSetRepositoryCachePolicyFactory for performance
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
	src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaTypeRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs
2016-01-22 17:08:21 +01:00
Shannon fe774f557c Fixes ms value: U4-7810 DatabaseServerRegistrar should not execute as soon as a request is made, this slows down app start 2016-01-22 17:06:14 +01:00
Shannon 3ecb9d0f86 U4-7807 Domain, language, public access cache (GetAll) caches not working when there are no items 2016-01-22 17:05:27 +01:00
Shannon f78a425985 U4-7816 The IsolatedCache instance in the RepositoryFactory differs from the ApplicationContext singleton instance 2016-01-22 16:37:47 +01:00
Sebastiaan Janssen 9f365727e0 Bumps version 2016-01-20 14:10:31 +01:00
Sebastiaan Janssen 74d73cfe94 U4-7796 Get UrlRewritingNet from the official NuGet location
#U4-7796 Fixed
2016-01-20 13:57:35 +01:00
Sebastiaan Janssen 7fb9d430a9 changes default upload limit to 50 mb 2016-01-20 10:54:43 +01:00
Sebastiaan Janssen 7cd8ba13c0 U4-7781 Setting a user's start node causes YSOD
#U4-7781 Fixed
2016-01-20 10:45:40 +01:00
Sebastiaan Janssen 1888888650 Update ImageProcessor, this time also in the nuspec file 2016-01-19 11:07:17 +01:00
910 changed files with 16006 additions and 34059 deletions
+2 -2
View File
@@ -175,8 +175,8 @@
<!-- Copy SQL CE -->
<ItemGroup>
<SQLCE4Files
Include="..\src\packages\SqlServerCE.4.0.0.0\**\*.*"
Exclude="..\src\packages\SqlServerCE.4.0.0.0\lib\**\*;..\src\packages\SqlServerCE.4.0.0.0\**\*.nu*"
Include="..\src\packages\SqlServerCE.4.0.0.1\**\*.*"
Exclude="..\src\packages\SqlServerCE.4.0.0.1\lib\**\*;..\src\packages\SqlServerCE.4.0.0.1\**\*.nu*"
/>
</ItemGroup>
+2 -3
View File
@@ -34,11 +34,11 @@
<dependency id="Newtonsoft.Json" version="[6.0.8, 7.0.0)" />
<dependency id="Examine" version="[0.1.68, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.3.2, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.5.0, 5.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.5.1, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 2.0.0)" />
<dependency id="Microsoft.AspNet.WebHelpers" version="[3.2.3, 4.0.0)" />
<dependency id="Microsoft.AspNet.WebPages.Data" version="[3.2.3, 4.0.0)" />
<dependency id="Umbraco.ModelsBuilder.AspNet" version="[2.2.0-beta003, 3.0.0)" />
<dependency id="UrlRewritingNet" version="[2.0.7, 3.0.0)" />
</dependencies>
</metadata>
<files>
@@ -73,7 +73,6 @@
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.xml" target="lib\UmbracoExamine.xml" />
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
<!-- Added to be able to produce a symbols package -->
@@ -17,11 +17,6 @@
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
xdt:Locator="Match(factoryType)"
xdt:Transform="SetAttributes(factoryType)" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
</namespaces>
</pages>
</system.web.webPages.razor>
<system.web>
+2 -5
View File
@@ -54,7 +54,7 @@
</providers>
</siteMap>
<httpRuntime xdt:Transform="InsertIfMissing" />
<httpRuntime targetFramework="4.5" maxRequestLength="1048576" fcnMode="Single" xdt:Transform="SetAttributes(targetFramework,fcnMode,maxRequestLength)" />
<httpRuntime targetFramework="4.5" maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(targetFramework,fcnMode,maxRequestLength)" />
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
@@ -66,7 +66,6 @@
<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" />
@@ -85,12 +84,10 @@
<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" />
</assemblies>
<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)" />
</assemblies>
</compilation>
@@ -146,7 +143,7 @@
<security xdt:Transform="InsertIfMissing">
<requestFiltering xdt:Transform="InsertIfMissing">
<requestLimits maxAllowedContentLength="1073741824" xdt:Transform="InsertIfMissing" />
<requestLimits maxAllowedContentLength="52428800" xdt:Transform="InsertIfMissing" />
</requestFiltering>
</security>
+33 -124
View File
@@ -1,127 +1,36 @@
<?xml version="1.0"?>
<trees xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--Content-->
<add alias="content" application="content"
xdt:Locator="Match(application,alias)"
xdt:Transform="RemoveAttributes(silent)" />
<add initialize="false" sortOrder="0" alias="contentRecycleBin" application="content" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.ContentRecycleBin, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add initialize="true" sortOrder="0" alias="content" application="content" title="Content" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.ContentTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<!--Media-->
<add initialize="true" sortOrder="0" alias="media" application="media" title="Media" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.MediaTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add initialize="false" sortOrder="0" alias="mediaRecycleBin" application="media" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.MediaRecycleBin, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<!--Settings-->
<add application="settings" alias="nodeTypes"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add initialize="true" sortOrder="0" alias="documentTypes" application="settings" title="Document Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.ContentTypeTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<add application="settings" alias="stylesheets" title="Stylesheets" type="umbraco.loadStylesheets, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, umbraco" iconClosed="" iconOpen="" initialize="false" sortOrder="0"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add alias="dictionary" application="settings"
xdt:Locator="Match(application,alias)"
xdt:Transform="RemoveAttributes(action)" />
<add application="settings" alias="languages" title="Languages" type="Umbraco.Web.Trees.LanguageTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="5"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" initialize="true" alias="mediaTypes" title="Media Types" type="Umbraco.Web.Trees.MediaTypeTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="7"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<!--Developer-->
<add alias="datatype" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add initialize="true" sortOrder="0" alias="datatypes" application="developer" title="Data Types" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packager" title="Packages" type="umbraco.loadPackager, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packagerPackages" title="Packager Packages" type="umbraco.loadPackages, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" initialize="false" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<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 application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="python"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<!--Users-->
<add application="users" alias="users" title="Users" type="umbraco.loadUsers, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="users" alias="userTypes" title="User Types" type="umbraco.cms.presentation.Trees.UserTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="users" alias="userPermissions" title="User Permissions" type="umbraco.cms.presentation.Trees.UserPermissions, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<!--Members-->
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="member" alias="memberGroup"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add application="member" sortOrder="2" alias="memberGroups" title="Member Groups" type="umbraco.loadMemberGroups, umbraco" iconClosed="icon-folder" iconOpen="icon-folder"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<add application="member" alias="memberType"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add application="member" sortOrder="1" alias="memberTypes" initialize="true" title="Member Types" type="Umbraco.Web.Trees.MemberTypeTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<!--Translation-->
<add silent="false" initialize="true" sortOrder="1" alias="openTasks" application="translation" title="Tasks assigned to you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadOpenTasks, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add alias="openTasks" application="translation"
xdt:Locator="Match(application,alias)"
xdt:Transform="RemoveAttributes(action)" />
<add silent="false" initialize="true" sortOrder="2" alias="yourTasks" application="translation" title="Tasks created by you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadYourTasks, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add alias="yourTasks" application="translation"
xdt:Locator="Match(application,alias)"
xdt:Transform="RemoveAttributes(action)" />
<add initialize="true" sortOrder="0" alias="content" application="content" title="Content" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.ContentTreeController, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add alias="content" xdt:Locator="Match(alias)" xdt:Transform="RemoveAttributes(silent)" />
<add initialize="false" sortOrder="0" alias="contentRecycleBin" application="content" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.ContentRecycleBin, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add initialize="true" sortOrder="0" alias="media" application="media" title="Media" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.MediaTreeController, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add initialize="false" sortOrder="0" alias="mediaRecycleBin" application="media" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.MediaRecycleBin, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="stylesheets" title="Stylesheets" type="umbraco.loadStylesheets, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, umbraco" iconClosed="" iconOpen="" initialize="false" sortOrder="0" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add alias="dictionary" xdt:Locator="Match(alias)" xdt:Transform="RemoveAttributes(action)" />
<add application="settings" alias="languages" title="Languages" type="Umbraco.Web.Trees.LanguageTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="5" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="mediaTypes" title="Media Types" type="umbraco.loadMediaTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="settings" alias="nodeTypes" title="Document Types" type="umbraco.loadNodeTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="7" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add initialize="true" sortOrder="0" alias="datatype" application="developer" title="Data Types" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="developer" alias="packager" title="Packages" type="umbraco.loadPackager, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="developer" alias="packagerPackages" title="Packager Packages" type="umbraco.loadPackages, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" initialize="false" sortOrder="3" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="users" alias="users" title="Users" type="umbraco.loadUsers, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="users" alias="userTypes" title="User Types" type="umbraco.cms.presentation.Trees.UserTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="users" alias="userPermissions" title="User Permissions" type="umbraco.cms.presentation.Trees.UserPermissions, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="member" alias="memberGroup" title="Member Groups" type="umbraco.loadMemberGroups, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add application="member" alias="memberType" title="Member Types" type="umbraco.loadMemberTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add silent="false" initialize="true" sortOrder="1" alias="openTasks" application="translation" title="Tasks assigned to you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadOpenTasks, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add alias="openTasks" xdt:Locator="Match(alias)" xdt:Transform="RemoveAttributes(action)" />
<add silent="false" initialize="true" sortOrder="2" alias="yourTasks" application="translation" title="Tasks created by you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadYourTasks, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
<add alias="yourTasks" xdt:Locator="Match(alias)" xdt:Transform="RemoveAttributes(action)" />
<add application="developer" alias="python" xdt:Locator="Match(alias)" xdt:Transform="Remove" />
</trees>
+1 -2
View File
@@ -1,3 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.4.0
beta2
7.3.8
+6 -6
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
</packageSources>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
</packageSources>
</configuration>
+8 -6
View File
@@ -47,13 +47,15 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net40" />
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
</packages>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.4.0")]
[assembly: AssemblyInformationalVersion("7.4.0-beta2")]
[assembly: AssemblyFileVersion("7.3.8")]
[assembly: AssemblyInformationalVersion("7.3.8")]
@@ -7,14 +7,22 @@ using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Interface describing this cache provider as a wrapper for another
/// </summary>
internal interface IRuntimeCacheProviderWrapper
{
IRuntimeCacheProvider InnerProvider { get; }
}
/// <summary>
/// A wrapper for any IRuntimeCacheProvider that ensures that all inserts and returns
/// are a deep cloned copy of the item when the item is IDeepCloneable and that tracks changes are
/// reset if the object is TracksChangesEntityBase
/// </summary>
internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider
internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider, IRuntimeCacheProviderWrapper
{
internal IRuntimeCacheProvider InnerProvider { get; private set; }
public IRuntimeCacheProvider InnerProvider { get; private set; }
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
{
@@ -11,35 +11,35 @@ namespace Umbraco.Core.Cache
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class DefaultRepositoryCachePolicy<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
/// <remarks>
/// This cache policy uses sliding expiration and caches instances for 5 minutes. However if allow zero count is true, then we use the
/// default policy with no expiry.
/// </remarks>
internal class DefaultRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private readonly RepositoryCachePolicyOptions _options;
protected IRuntimeCacheProvider Cache { get; private set; }
private Action _action;
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options)
{
if (cache == null) throw new ArgumentNullException("cache");
: base(cache)
{
if (options == null) throw new ArgumentNullException("options");
_options = options;
Cache = cache;
_options = options;
}
public string GetCacheIdKey(object id)
protected string GetCacheIdKey(object id)
{
if (id == null) throw new ArgumentNullException("id");
return string.Format("{0}{1}", GetCacheTypeKey(), id);
}
public string GetCacheTypeKey()
protected string GetCacheTypeKey()
{
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
}
public void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
public override void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
{
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
@@ -54,7 +54,9 @@ namespace Umbraco.Core.Cache
//just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity);
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity,
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
@@ -79,24 +81,29 @@ namespace Umbraco.Core.Cache
}
}
public void Remove(TEntity entity, Action<TEntity> persistMethod)
public override void Remove(TEntity entity, Action<TEntity> persistMethod)
{
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
persistMethod(entity);
//set the disposal action
var cacheKey = GetCacheIdKey(entity.Id);
SetCacheAction(() =>
try
{
Cache.ClearCacheItem(cacheKey);
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetCacheTypeKey());
});
persistMethod(entity);
}
finally
{
//set the disposal action
var cacheKey = GetCacheIdKey(entity.Id);
SetCacheAction(() =>
{
Cache.ClearCacheItem(cacheKey);
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
}
public TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
public override TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
{
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
@@ -113,13 +120,13 @@ namespace Umbraco.Core.Cache
return entity;
}
public TEntity Get(TId id)
public override TEntity Get(TId id)
{
var cacheKey = GetCacheIdKey(id);
return Cache.GetCacheItem<TEntity>(cacheKey);
}
public bool Exists(TId id, Func<TId, bool> getFromRepo)
public override bool Exists(TId id, Func<TId, bool> getFromRepo)
{
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
@@ -128,7 +135,7 @@ namespace Umbraco.Core.Cache
return fromCache != null || getFromRepo(id);
}
public virtual TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
{
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
@@ -158,8 +165,7 @@ namespace Umbraco.Core.Cache
else if (_options.GetAllCacheAllowZeroCount)
{
//if the repository allows caching a zero count, then check the zero count cache
var zeroCount = Cache.GetCacheItem<TEntity[]>(GetCacheTypeKey());
if (zeroCount != null && zeroCount.Any() == false)
if (HasZeroCountCache())
{
//there is a zero count cache so return an empty list
return new TEntity[] {};
@@ -179,28 +185,27 @@ namespace Umbraco.Core.Cache
return entityCollection;
}
/// <summary>
/// Looks up the zero count cache, must return null if it doesn't exist
/// </summary>
/// <returns></returns>
protected bool HasZeroCountCache()
{
var zeroCount = Cache.GetCacheItem<TEntity[]>(GetCacheTypeKey());
return (zeroCount != null && zeroCount.Any() == false);
}
/// <summary>
/// Performs the lookup for all entities of this type from the cache
/// </summary>
/// <returns></returns>
protected virtual TEntity[] GetAllFromCache()
protected TEntity[] GetAllFromCache()
{
var allEntities = Cache.GetCacheItemsByKeySearch<TEntity>(GetCacheTypeKey())
.WhereNotNull()
.ToArray();
return allEntities.Any() ? allEntities : new TEntity[] {};
}
/// <summary>
/// The disposal performs the caching
/// </summary>
protected override void DisposeResources()
{
if (_action != null)
{
_action();
}
}
}
/// <summary>
/// Sets the action to execute on disposal for a single entity
@@ -216,7 +221,9 @@ namespace Umbraco.Core.Cache
//just to be safe, we cannot cache an item without an identity
if (entity.HasIdentity)
{
Cache.InsertCacheItem(cacheKey, () => entity);
Cache.InsertCacheItem(cacheKey, () => entity,
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
});
}
@@ -235,6 +242,7 @@ namespace Umbraco.Core.Cache
{
//there was nothing returned but we want to cache a zero count result so add an TEntity[] to the cache
// to signify that there is a zero count cache
//NOTE: Don't set expiry/sliding for a zero count
Cache.InsertCacheItem(GetCacheTypeKey(), () => new TEntity[] {});
}
else
@@ -247,20 +255,14 @@ namespace Umbraco.Core.Cache
//just to be safe, we cannot cache an item without an identity
if (localCopy.HasIdentity)
{
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy);
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy,
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
}
}
});
}
/// <summary>
/// Sets the action to execute on disposal
/// </summary>
/// <param name="action"></param>
protected void SetCacheAction(Action action)
{
_action = action;
}
}
}
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Collections;
using Umbraco.Core.Models.EntityBase;
@@ -9,11 +11,157 @@ namespace Umbraco.Core.Cache
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TId"></typeparam>
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : DefaultRepositoryCachePolicy<TEntity, TId>
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
where TEntity : class, IAggregateRoot
{
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache) : base(cache, new RepositoryCachePolicyOptions())
private readonly Func<TEntity, TId> _getEntityId;
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
private readonly bool _expires;
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
: base(cache)
{
_getEntityId = getEntityId;
_getAllFromRepo = getAllFromRepo;
_expires = expires;
}
private bool? _hasZeroCountCache;
protected string GetCacheTypeKey()
{
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
}
public override void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
{
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
try
{
persistMethod(entity);
//set the disposal action
SetCacheAction(() =>
{
//Clear all
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
catch
{
//set the disposal action
SetCacheAction(() =>
{
//Clear all
Cache.ClearCacheItem(GetCacheTypeKey());
});
throw;
}
}
public override void Remove(TEntity entity, Action<TEntity> persistMethod)
{
if (entity == null) throw new ArgumentNullException("entity");
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
try
{
persistMethod(entity);
}
finally
{
//set the disposal action
SetCacheAction(() =>
{
//Clear all
Cache.ClearCacheItem(GetCacheTypeKey());
});
}
}
public override TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
{
//Force get all with cache
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
//we don't have anything in cache (this should never happen), just return from the repo
if (found == null) return getFromRepo(id);
var entity = found.FirstOrDefault(x => _getEntityId(x).Equals(id));
if (entity == null) return null;
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
return (TEntity)entity.DeepClone();
}
public override TEntity Get(TId id)
{
//Force get all with cache
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
//we don't have anything in cache (this should never happen), just return null
if (found == null) return null;
var entity = found.FirstOrDefault(x => _getEntityId(x).Equals(id));
if (entity == null) return null;
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
return (TEntity)entity.DeepClone();
}
public override bool Exists(TId id, Func<TId, bool> getFromRepo)
{
//Force get all with cache
var found = GetAll(new TId[] {}, ids => _getAllFromRepo().WhereNotNull());
//we don't have anything in cache (this should never happen), just return from the repo
return found == null
? getFromRepo(id)
: found.Any(x => _getEntityId(x).Equals(id));
}
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
{
//process getting all including setting the cache callback
var result = PerformGetAll(getFromRepo);
//now that the base result has been calculated, they will all be cached.
// Now we can just filter by ids if they have been supplied
return (ids.Any()
? result.Where(x => ids.Contains(_getEntityId(x))).ToArray()
: result)
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
.Select(x => (TEntity)x.DeepClone())
.ToArray();
}
private TEntity[] PerformGetAll(Func<TId[], IEnumerable<TEntity>> getFromRepo)
{
var allEntities = GetAllFromCache();
if (allEntities.Any())
{
return allEntities;
}
//check the zero count cache
if (HasZeroCountCache())
{
//there is a zero count cache so return an empty list
return new TEntity[] { };
}
//we need to do the lookup from the repo
var entityCollection = getFromRepo(new TId[] {})
//ensure we don't include any null refs in the returned collection!
.WhereNotNull()
.ToArray();
//set the disposal action
SetCacheAction(entityCollection);
return entityCollection;
}
/// <summary>
@@ -21,37 +169,61 @@ namespace Umbraco.Core.Cache
/// </summary>
/// <param name="cacheKey"></param>
/// <param name="entity"></param>
protected override void SetCacheAction(string cacheKey, TEntity entity)
protected void SetCacheAction(string cacheKey, TEntity entity)
{
//do nothing
//No-op
}
/// <summary>
/// Sets the action to execute on disposal for an entity collection
/// </summary>
/// <param name="ids"></param>
/// <param name="entityCollection"></param>
protected override void SetCacheAction(TId[] ids, TEntity[] entityCollection)
protected void SetCacheAction(TEntity[] entityCollection)
{
//for this type of caching policy, we don't want to cache any GetAll request containing specific Ids
if (ids.Any()) return;
//set the disposal action
SetCacheAction(() =>
{
//We want to cache the result as a single collection
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection));
if (_expires)
{
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection),
timeout: TimeSpan.FromMinutes(5),
isSliding: true);
}
else
{
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection));
}
});
}
/// <summary>
/// Looks up the zero count cache, must return null if it doesn't exist
/// </summary>
/// <returns></returns>
protected bool HasZeroCountCache()
{
if (_hasZeroCountCache.HasValue)
return _hasZeroCountCache.Value;
_hasZeroCountCache = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey()) != null;
return _hasZeroCountCache.Value;
}
/// <summary>
/// This policy will cache the full data set as a single collection
/// </summary>
/// <returns></returns>
protected override TEntity[] GetAllFromCache()
protected TEntity[] GetAllFromCache()
{
var found = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey());
//This method will get called before checking for zero count cache, so we'll just set the flag here
_hasZeroCountCache = found != null;
return found == null ? new TEntity[] { } : found.WhereNotNull().ToArray();
}
}
}
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
@@ -11,15 +13,21 @@ namespace Umbraco.Core.Cache
where TEntity : class, IAggregateRoot
{
private readonly IRuntimeCacheProvider _runtimeCache;
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache)
private readonly Func<TEntity, TId> _getEntityId;
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
private readonly bool _expires;
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
{
_runtimeCache = runtimeCache;
_getEntityId = getEntityId;
_getAllFromRepo = getAllFromRepo;
_expires = expires;
}
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
{
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache);
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _getEntityId, _getAllFromRepo, _expires);
}
}
}
@@ -10,9 +10,7 @@ namespace Umbraco.Core.Cache
TEntity Get(TId id, Func<TId, TEntity> getFromRepo);
TEntity Get(TId id);
bool Exists(TId id, Func<TId, bool> getFromRepo);
string GetCacheIdKey(object id);
string GetCacheTypeKey();
void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod);
void Remove(TEntity entity, Action<TEntity> persistMethod);
TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo);
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Cache
/// </remarks>
public class IsolatedRuntimeCache
{
private readonly Func<Type, IRuntimeCacheProvider> _cacheFactory;
internal Func<Type, IRuntimeCacheProvider> CacheFactory { get; set; }
/// <summary>
/// Constructor that allows specifying a factory for the type of runtime isolated cache to create
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Cache
/// <param name="cacheFactory"></param>
public IsolatedRuntimeCache(Func<Type, IRuntimeCacheProvider> cacheFactory)
{
_cacheFactory = cacheFactory;
CacheFactory = cacheFactory;
}
private readonly ConcurrentDictionary<Type, IRuntimeCacheProvider> _isolatedCache = new ConcurrentDictionary<Type, IRuntimeCacheProvider>();
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Cache
/// <returns></returns>
public IRuntimeCacheProvider GetOrCreateCache<T>()
{
return _isolatedCache.GetOrAdd(typeof(T), type => _cacheFactory(type));
return _isolatedCache.GetOrAdd(typeof(T), type => CacheFactory(type));
}
/// <summary>
@@ -41,7 +41,7 @@ namespace Umbraco.Core.Cache
/// <returns></returns>
public IRuntimeCacheProvider GetOrCreateCache(Type type)
{
return _isolatedCache.GetOrAdd(type, t => _cacheFactory(t));
return _isolatedCache.GetOrAdd(type, t => CacheFactory(t));
}
/// <summary>
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Cache
{
internal abstract class RepositoryCachePolicyBase<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
where TEntity : class, IAggregateRoot
{
private Action _action;
protected RepositoryCachePolicyBase(IRuntimeCacheProvider cache)
{
if (cache == null) throw new ArgumentNullException("cache");
Cache = cache;
}
protected IRuntimeCacheProvider Cache { get; private set; }
/// <summary>
/// The disposal performs the caching
/// </summary>
protected override void DisposeResources()
{
if (_action != null)
{
_action();
}
}
/// <summary>
/// Sets the action to execute on disposal
/// </summary>
/// <param name="action"></param>
protected void SetCacheAction(Action action)
{
_action = action;
}
public abstract TEntity Get(TId id, Func<TId, TEntity> getFromRepo);
public abstract TEntity Get(TId id);
public abstract bool Exists(TId id, Func<TId, bool> getFromRepo);
public abstract void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod);
public abstract void Remove(TEntity entity, Action<TEntity> persistMethod);
public abstract TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo);
}
}
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Cache
protected override void SetCacheAction(TId[] ids, TEntity[] entityCollection)
{
//do nothing
//no-op
}
}
}
+44 -46
View File
@@ -18,12 +18,8 @@ namespace Umbraco.Core
/// </summary>
public class CacheHelper
{
private readonly IsolatedRuntimeCache _isolatedCacheManager;
private readonly ICacheProvider _requestCache;
private static readonly ICacheProvider NullRequestCache = new NullCacheProvider();
private readonly ICacheProvider _staticCache;
private static readonly ICacheProvider NullStaticCache = new NullCacheProvider();
private readonly IRuntimeCacheProvider _runtimeCache;
private static readonly IRuntimeCacheProvider NullRuntimeCache = new NullCacheProvider();
/// <summary>
@@ -90,45 +86,33 @@ namespace Umbraco.Core
if (staticCacheProvider == null) throw new ArgumentNullException("staticCacheProvider");
if (requestCacheProvider == null) throw new ArgumentNullException("requestCacheProvider");
if (isolatedCacheManager == null) throw new ArgumentNullException("isolatedCacheManager");
_runtimeCache = httpCacheProvider;
_staticCache = staticCacheProvider;
_requestCache = requestCacheProvider;
_isolatedCacheManager = isolatedCacheManager;
RuntimeCache = httpCacheProvider;
StaticCache = staticCacheProvider;
RequestCache = requestCacheProvider;
IsolatedRuntimeCache = isolatedCacheManager;
}
/// <summary>
/// Returns the current Request cache
/// </summary>
public ICacheProvider RequestCache
{
get { return _requestCache; }
}
public ICacheProvider RequestCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public ICacheProvider StaticCache
{
get { return _staticCache; }
}
public ICacheProvider StaticCache { get; internal set; }
/// <summary>
/// Returns the current Runtime cache
/// </summary>
public IRuntimeCacheProvider RuntimeCache
{
get { return _runtimeCache; }
}
public IRuntimeCacheProvider RuntimeCache { get; internal set; }
/// <summary>
/// Returns the current Isolated Runtime cache manager
/// </summary>
public IsolatedRuntimeCache IsolatedRuntimeCache
{
get { return _isolatedCacheManager; }
}
#region Legacy Runtime/Http Cache accessors
public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; }
#region Legacy Runtime/Http Cache accessors
/// <summary>
/// Clears the item in umbraco's runtime cache
@@ -137,8 +121,8 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearAllCache()
{
_runtimeCache.ClearAllCache();
_isolatedCacheManager.ClearAllCaches();
RuntimeCache.ClearAllCache();
IsolatedRuntimeCache.ClearAllCaches();
}
/// <summary>
@@ -149,7 +133,7 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheItem(string key)
{
_runtimeCache.ClearCacheItem(key);
RuntimeCache.ClearCacheItem(key);
}
@@ -161,7 +145,7 @@ namespace Umbraco.Core
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
public void ClearCacheObjectTypes(string typeName)
{
_runtimeCache.ClearCacheObjectTypes(typeName);
RuntimeCache.ClearCacheObjectTypes(typeName);
}
/// <summary>
@@ -171,7 +155,7 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheObjectTypes<T>()
{
_runtimeCache.ClearCacheObjectTypes<T>();
RuntimeCache.ClearCacheObjectTypes<T>();
}
/// <summary>
@@ -182,7 +166,7 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeySearch(string keyStartsWith)
{
_runtimeCache.ClearCacheByKeySearch(keyStartsWith);
RuntimeCache.ClearCacheByKeySearch(keyStartsWith);
}
/// <summary>
@@ -193,14 +177,14 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearCacheByKeyExpression(string regexString)
{
_runtimeCache.ClearCacheByKeyExpression(regexString);
RuntimeCache.ClearCacheByKeyExpression(regexString);
}
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
{
return _runtimeCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
return RuntimeCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
}
/// <summary>
@@ -213,7 +197,7 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey)
{
return _runtimeCache.GetCacheItem<TT>(cacheKey);
return RuntimeCache.GetCacheItem<TT>(cacheKey);
}
/// <summary>
@@ -227,7 +211,7 @@ namespace Umbraco.Core
[EditorBrowsable(EditorBrowsableState.Never)]
public TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
{
return _runtimeCache.GetCacheItem<TT>(cacheKey, getCacheItem);
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem);
}
@@ -244,7 +228,7 @@ namespace Umbraco.Core
public TT GetCacheItem<TT>(string cacheKey,
TimeSpan timeout, Func<TT> getCacheItem)
{
return _runtimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
}
@@ -263,7 +247,7 @@ namespace Umbraco.Core
CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return _runtimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
}
@@ -283,7 +267,7 @@ namespace Umbraco.Core
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout,
Func<TT> getCacheItem)
{
return _runtimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
}
@@ -306,7 +290,7 @@ namespace Umbraco.Core
TimeSpan timeout,
Func<TT> getCacheItem)
{
var cache = _runtimeCache as HttpRuntimeCacheProvider;
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
@@ -330,7 +314,7 @@ namespace Umbraco.Core
CacheDependency cacheDependency,
Func<TT> getCacheItem)
{
var cache = _runtimeCache as HttpRuntimeCacheProvider;
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
@@ -352,7 +336,7 @@ namespace Umbraco.Core
CacheItemPriority priority,
Func<T> getCacheItem)
{
_runtimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
}
@@ -371,7 +355,7 @@ namespace Umbraco.Core
TimeSpan timeout,
Func<T> getCacheItem)
{
_runtimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
}
/// <summary>
@@ -390,7 +374,7 @@ namespace Umbraco.Core
TimeSpan timeout,
Func<T> getCacheItem)
{
var cache = _runtimeCache as HttpRuntimeCacheProvider;
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
@@ -416,7 +400,7 @@ namespace Umbraco.Core
TimeSpan? timeout,
Func<T> getCacheItem)
{
var cache = _runtimeCache as HttpRuntimeCacheProvider;
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
if (cache != null)
{
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
@@ -425,6 +409,20 @@ namespace Umbraco.Core
}
#endregion
}
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider(IRuntimeCacheProvider runtimeCache)
{
HttpRuntimeCacheProvider cache;
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper;
if (wrapper != null)
{
cache = wrapper.InnerProvider as HttpRuntimeCacheProvider;
}
else
{
cache = RuntimeCache as HttpRuntimeCacheProvider;
}
return cache;
}
}
}
@@ -14,18 +14,24 @@ namespace Umbraco.Core.Collections
/// <typeparam name="T"></typeparam>
internal class DeepCloneableList<T> : List<T>, IDeepCloneable, IRememberBeingDirty
{
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Collections.Generic.List`1"/> class that is empty and has the default initial capacity.
/// </summary>
public DeepCloneableList()
private readonly ListCloneBehavior _listCloneBehavior;
public DeepCloneableList(ListCloneBehavior listCloneBehavior)
{
_listCloneBehavior = listCloneBehavior;
}
public DeepCloneableList(IEnumerable<T> collection, ListCloneBehavior listCloneBehavior) : base(collection)
{
_listCloneBehavior = listCloneBehavior;
}
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Collections.Generic.List`1"/> class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
/// Default behavior is CloneOnce
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new list.</param><exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is null.</exception>
public DeepCloneableList(IEnumerable<T> collection) : base(collection)
/// <param name="collection"></param>
public DeepCloneableList(IEnumerable<T> collection)
: this(collection, ListCloneBehavior.CloneOnce)
{
}
@@ -35,20 +41,47 @@ namespace Umbraco.Core.Collections
/// <returns></returns>
public object DeepClone()
{
var newList = new DeepCloneableList<T>();
foreach (var item in this)
switch (_listCloneBehavior)
{
var dc = item as IDeepCloneable;
if (dc != null)
{
newList.Add((T) dc.DeepClone());
}
else
{
newList.Add(item);
}
case ListCloneBehavior.CloneOnce:
//we are cloning once, so create a new list in none mode
// and deep clone all items into it
var newList = new DeepCloneableList<T>(ListCloneBehavior.None);
foreach (var item in this)
{
var dc = item as IDeepCloneable;
if (dc != null)
{
newList.Add((T)dc.DeepClone());
}
else
{
newList.Add(item);
}
}
return newList;
case ListCloneBehavior.None:
//we are in none mode, so just return a new list with the same items
return new DeepCloneableList<T>(this, ListCloneBehavior.None);
case ListCloneBehavior.Always:
//always clone to new list
var newList2 = new DeepCloneableList<T>(ListCloneBehavior.Always);
foreach (var item in this)
{
var dc = item as IDeepCloneable;
if (dc != null)
{
newList2.Add((T)dc.DeepClone());
}
else
{
newList2.Add(item);
}
}
return newList2;
default:
throw new ArgumentOutOfRangeException();
}
return newList;
}
public bool IsDirty()
@@ -0,0 +1,20 @@
namespace Umbraco.Core.Collections
{
internal enum ListCloneBehavior
{
/// <summary>
/// When set, DeepClone will clone the items one time and the result list behavior will be None
/// </summary>
CloneOnce,
/// <summary>
/// When set, DeepClone will not clone any items
/// </summary>
None,
/// <summary>
/// When set, DeepClone will always clone all items
/// </summary>
Always
}
}
@@ -280,18 +280,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
}
}
[ConfigurationProperty("EnableInheritedDocumentTypes")]
internal InnerTextConfigurationElement<bool> EnableInheritedDocumentTypes
{
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>) this["EnableInheritedDocumentTypes"],
//set the default
true);
}
}
string IContentSection.NotificationEmailAddress
{
get { return Notifications.NotificationEmailAddress; }
@@ -426,10 +414,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return DefaultDocumentTypeProperty; }
}
bool IContentSection.EnableInheritedDocumentTypes
{
get { return EnableInheritedDocumentTypes; }
}
}
}
@@ -59,7 +59,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool GlobalPreviewStorageEnabled { get; }
string DefaultDocumentTypeProperty { get; }
bool EnableInheritedDocumentTypes { get; }
}
}
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.4.0");
private static readonly Version Version = new Version("7.3.8");
/// <summary>
/// Gets the current version of Umbraco.
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "beta2"; } }
public static string CurrentComment { get { return ""; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
+2 -18
View File
@@ -59,7 +59,7 @@
public const string Content = "content";
/// <summary>
/// alias for the member tree.
/// alias for the media tree.
/// </summary>
public const string Members = "member";
@@ -71,7 +71,7 @@
/// <summary>
/// alias for the datatype tree.
/// </summary>
public const string DataTypes = "dataTypes";
public const string DataTypes = "datatype";
/// <summary>
/// alias for the dictionary tree.
@@ -80,22 +80,6 @@
public const string Stylesheets = "stylesheets";
/// <summary>
/// alias for the document type tree.
/// </summary>
public const string DocumentTypes = "documentTypes";
/// <summary>
/// alias for the media type tree.
/// </summary>
public const string MediaTypes = "mediaTypes";
/// <summary>
/// alias for the member type tree.
/// </summary>
public const string MemberTypes = "memberTypes";
/// <summary>
/// alias for the template tree.
/// </summary>
-53
View File
@@ -1,53 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core
{
public static partial class Constants
{
public static class Icons
{
/// <summary>
/// System contenttype icon
/// </summary>
public const string ContentType = "icon-arrangement";
/// <summary>
/// System datatype icon
/// </summary>
public const string DataType = "icon-autofill";
/// <summary>
/// System property editor icon
/// </summary>
public const string PropertyEditor = "icon-autofill";
/// <summary>
/// System macro icon
/// </summary>
public const string Macro = "icon-settings-alt";
/// <summary>
/// System member icon
/// </summary>
public const string Member = "icon-user";
/// <summary>
/// System member icon
/// </summary>
public const string MemberType = "icon-users";
/// <summary>
/// System member icon
/// </summary>
public const string Template = "icon-layout";
}
}
}
-52
View File
@@ -9,36 +9,6 @@ namespace Umbraco.Core
/// </summary>
public static class ObjectTypes
{
/// <summary>
/// Guid for a data type container
/// </summary>
public const string DataTypeContainer = "521231E3-8B37-469C-9F9D-51AFC91FEB7B";
/// <summary>
/// Guid for a data type container
/// </summary>
public static readonly Guid DataTypeContainerGuid = new Guid(DataTypeContainer);
/// <summary>
/// Guid for a doc type container
/// </summary>
public const string DocumentTypeContainer = "2F7A2769-6B0B-4468-90DD-AF42D64F7F16";
/// <summary>
/// Guid for a doc type container
/// </summary>
public static readonly Guid DocumentTypeContainerGuid = new Guid(DocumentTypeContainer);
/// <summary>
/// Guid for a doc type container
/// </summary>
public const string MediaTypeContainer = "42AEF799-B288-4744-9B10-BE144B73CDC4";
/// <summary>
/// Guid for a doc type container
/// </summary>
public static readonly Guid MediaTypeContainerGuid = new Guid(MediaTypeContainer);
/// <summary>
/// Guid for a Content Item object.
/// </summary>
@@ -59,11 +29,6 @@ namespace Umbraco.Core
/// </summary>
public const string DataType = "30A2A501-1978-4DDB-A57B-F7EFED43BA3C";
/// <summary>
/// Guid for a DataType object.
/// </summary>
public static readonly Guid DataTypeGuid = new Guid(DataType);
/// <summary>
/// Guid for a Document object.
/// </summary>
@@ -74,11 +39,6 @@ namespace Umbraco.Core
/// </summary>
public const string DocumentType = "A2CB7800-F571-4787-9638-BC48539A0EFB";
/// <summary>
/// Guid for a Document Type object.
/// </summary>
public static readonly Guid DocumentTypeGuid = new Guid(DocumentType);
/// <summary>
/// Guid for a Media object.
/// </summary>
@@ -94,11 +54,6 @@ namespace Umbraco.Core
/// </summary>
public const string MediaType = "4EA4382B-2F5A-4C2B-9587-AE9B3CF3602E";
/// <summary>
/// Guid for a Media Type object.
/// </summary>
public static readonly Guid MediaTypeGuid = new Guid(MediaType);
/// <summary>
/// Guid for a Member object.
/// </summary>
@@ -114,11 +69,6 @@ namespace Umbraco.Core
/// </summary>
public const string MemberType = "9B5416FB-E72F-45A9-A07B-5A9A2709CE43";
/// <summary>
/// Guid for a Member Type object.
/// </summary>
public static readonly Guid MemberTypeGuid = new Guid(MemberType);
/// <summary>
/// Guid for a Stylesheet object.
/// </summary>
@@ -142,8 +92,6 @@ namespace Umbraco.Core
/// Guid for a Lock object.
/// </summary>
public const string LockObject = "87A9F1FF-B1E4-4A25-BABB-465A4A47EC41";
}
}
}
@@ -158,11 +158,6 @@ namespace Umbraco.Core
/// </summary>
public const string IntegerAlias = "Umbraco.Integer";
/// <summary>
/// Alias for the Decimal datatype.
/// </summary>
public const string DecimalAlias = "Umbraco.Decimal";
/// <summary>
/// Alias for the listview datatype.
/// </summary>
@@ -1,31 +0,0 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for property-type groups conventions that are used within the Umbraco core.
/// </summary>
public static class PropertyTypeGroups
{
/// <summary>
/// Guid for a Image PropertyTypeGroup object.
/// </summary>
public const string Image = "79ED4D07-254A-42CF-8FA9-EBE1C116A596";
/// <summary>
/// Guid for a File PropertyTypeGroup object.
/// </summary>
public const string File = "50899F9C-023A-4466-B623-ABA9049885FE";
/// <summary>
/// Guid for a Image PropertyTypeGroup object.
/// </summary>
public const string Contents = "79995FA2-63EE-453C-A29B-2E66F324CDBE";
/// <summary>
/// Guid for a Image PropertyTypeGroup object.
/// </summary>
public const string Membership = "0756729D-D665-46E3-B84A-37ACEAA614F8";
}
}
}
+6
View File
@@ -10,6 +10,12 @@ namespace Umbraco.Core
/// </summary>
public static class Web
{
public const string UmbracoContextDataToken = "umbraco-context";
public const string UmbracoDataToken = "umbraco";
public const string PublishedDocumentRequestDataToken = "umbraco-doc-request";
public const string CustomRouteDataToken = "umbraco-custom-route";
public const string UmbracoRouteDefinitionDataToken = "umbraco-route-def";
/// <summary>
/// The preview cookie name
/// </summary>
+12 -4
View File
@@ -136,7 +136,10 @@ namespace Umbraco.Core
{
try
{
x.OnApplicationInitialized(UmbracoApplication, ApplicationContext);
using (ProfilingLogger.DebugDuration<CoreBootManager>(string.Format("Executing {0} in ApplicationInitialized", x.GetType())))
{
x.OnApplicationInitialized(UmbracoApplication, ApplicationContext);
}
}
catch (Exception ex)
{
@@ -299,7 +302,10 @@ namespace Umbraco.Core
{
try
{
x.OnApplicationStarting(UmbracoApplication, ApplicationContext);
using (ProfilingLogger.DebugDuration<CoreBootManager>(string.Format("Executing {0} in ApplicationStarting", x.GetType())))
{
x.OnApplicationStarting(UmbracoApplication, ApplicationContext);
}
}
catch (Exception ex)
{
@@ -350,7 +356,10 @@ namespace Umbraco.Core
{
try
{
x.OnApplicationStarted(UmbracoApplication, ApplicationContext);
using (ProfilingLogger.DebugDuration<CoreBootManager>(string.Format("Executing {0} in ApplicationStarted", x.GetType())))
{
x.OnApplicationStarted(UmbracoApplication, ApplicationContext);
}
}
catch (Exception ex)
{
@@ -437,7 +446,6 @@ namespace Umbraco.Core
new Lazy<Type>(() => typeof (DelimitedManifestValueValidator)),
new Lazy<Type>(() => typeof (EmailValidator)),
new Lazy<Type>(() => typeof (IntegerValidator)),
new Lazy<Type>(() => typeof (DecimalValidator)),
});
//by default we'll use the db server registrar unless the developer has the legacy
+44 -21
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Web;
@@ -12,6 +13,12 @@ namespace Umbraco.Core
/// </summary>
public class DisposableTimer : DisposableObject
{
private readonly ILogger _logger;
private readonly LogType? _logType;
private readonly IProfiler _profiler;
private readonly Type _loggerType;
private readonly string _endMessage;
private readonly IDisposable _profilerStep;
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
private readonly Action<long> _callback;
@@ -25,25 +32,12 @@ namespace Umbraco.Core
if (logger == null) throw new ArgumentNullException("logger");
if (loggerType == null) throw new ArgumentNullException("loggerType");
_callback = x =>
{
if (profiler != null)
{
profiler.DisposeIfDisposable();
}
switch (logType)
{
case LogType.Debug:
logger.Debug(loggerType, () => endMessage + " (took " + x + "ms)");
break;
case LogType.Info:
logger.Info(loggerType, () => endMessage + " (took " + x + "ms)");
break;
default:
throw new ArgumentOutOfRangeException("logType");
}
};
_logger = logger;
_logType = logType;
_profiler = profiler;
_loggerType = loggerType;
_endMessage = endMessage;
switch (logType)
{
case LogType.Debug:
@@ -58,7 +52,7 @@ namespace Umbraco.Core
if (profiler != null)
{
profiler.Step(loggerType, startMessage);
_profilerStep = profiler.Step(loggerType, startMessage);
}
}
@@ -223,7 +217,36 @@ namespace Umbraco.Core
/// </summary>
protected override void DisposeResources()
{
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
if (_profiler != null)
{
_profiler.DisposeIfDisposable();
}
if (_profilerStep != null)
{
_profilerStep.Dispose();
}
if (_logType.HasValue && _endMessage.IsNullOrWhiteSpace() == false && _loggerType != null && _logger != null)
{
switch (_logType)
{
case LogType.Debug:
_logger.Debug(_loggerType, () => _endMessage + " (took " + Stopwatch.ElapsedMilliseconds + "ms)");
break;
case LogType.Info:
_logger.Info(_loggerType, () => _endMessage + " (took " + Stopwatch.ElapsedMilliseconds + "ms)");
break;
default:
throw new ArgumentOutOfRangeException("logType");
}
}
if (_callback != null)
{
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
}
}
}
@@ -1,21 +0,0 @@
using System;
namespace Umbraco.Core.Exceptions
{
internal class DataOperationException<T> : Exception
{
public T Operation { get; private set; }
public DataOperationException(T operation, string message)
:base(message)
{
Operation = operation;
}
public DataOperationException(T operation)
: base("Data operation exception: " + operation)
{
Operation = operation;
}
}
}
@@ -3,41 +3,22 @@
namespace Umbraco.Core.Exceptions
{
public class InvalidCompositionException : Exception
{
public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliass)
{
ContentTypeAlias = contentTypeAlias;
AddedCompositionAlias = addedCompositionAlias;
PropertyTypeAliases = propertyTypeAliass;
}
{
public string ContentTypeAlias { get; set; }
public InvalidCompositionException(string contentTypeAlias, string[] propertyTypeAliass)
{
ContentTypeAlias = contentTypeAlias;
PropertyTypeAliases = propertyTypeAliass;
}
public string AddedCompositionAlias { get; set; }
public string ContentTypeAlias { get; private set; }
public string AddedCompositionAlias { get; private set; }
public string[] PropertyTypeAliases { get; private set; }
public string PropertyTypeAlias { get; set; }
public override string Message
{
get
{
return AddedCompositionAlias.IsNullOrWhiteSpace()
? string.Format(
"ContentType with alias '{0}' has an invalid composition " +
"and there was a conflict on the following PropertyTypes: '{1}'. " +
return string.Format(
"InvalidCompositionException - ContentType with alias '{0}' was added as a Compsition to ContentType with alias '{1}', " +
"but there was a conflict on the PropertyType alias '{2}'. " +
"PropertyTypes must have a unique alias across all Compositions in order to compose a valid ContentType Composition.",
ContentTypeAlias, string.Join(", ", PropertyTypeAliases))
: string.Format(
"ContentType with alias '{0}' was added as a Composition to ContentType with alias '{1}', " +
"but there was a conflict on the following PropertyTypes: '{2}'. " +
"PropertyTypes must have a unique alias across all Compositions in order to compose a valid ContentType Composition.",
AddedCompositionAlias, ContentTypeAlias, string.Join(", ", PropertyTypeAliases));
AddedCompositionAlias, ContentTypeAlias, PropertyTypeAlias);
}
}
}
+1 -5
View File
@@ -66,7 +66,7 @@ namespace Umbraco.Core.IO
return viewContent;
}
internal static string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null)
internal static string GetDefaultFileContent(string layoutPageAlias = null)
{
var design = @"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
@@ -76,10 +76,6 @@ namespace Umbraco.Core.IO
if (layoutPageAlias.IsNullOrWhiteSpace() == false)
design = design.Replace("null", string.Format("\"{0}.cshtml\"", layoutPageAlias));
if (modelClassName.IsNullOrWhiteSpace() == false)
design = design.Replace(".UmbracoTemplatePage", string.Format(".UmbracoTemplatePage<{0}>", modelClassName));
return design;
}
+12
View File
@@ -340,6 +340,18 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if(Key == Guid.Empty)
Key = Guid.NewGuid();
}
/// <summary>
/// Method to call when Entity is being updated
/// </summary>
+19
View File
@@ -53,6 +53,9 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets or sets the alias of the default Template.
/// TODO: This should be ignored from cloning!!!!!!!!!!!!!!
/// - but to do that we have to implement callback hacks, this needs to be fixed in v8,
/// we should not store direct entity
/// </summary>
[IgnoreDataMember]
public ITemplate DefaultTemplate
@@ -79,6 +82,9 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets or Sets a list of Templates which are allowed for the ContentType
/// TODO: This should be ignored from cloning!!!!!!!!!!!!!!
/// - but to do that we have to implement callback hacks, this needs to be fixed in v8,
/// we should not store direct entity
/// </summary>
[DataMember]
public IEnumerable<ITemplate> AllowedTemplates
@@ -137,6 +143,19 @@ namespace Umbraco.Core.Models
return result;
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
@@ -1,17 +0,0 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Used when determining available compositions for a given content type
/// </summary>
internal class ContentTypeAvailableCompositionsResult
{
public ContentTypeAvailableCompositionsResult(IContentTypeComposition composition, bool allowed)
{
Composition = composition;
Allowed = allowed;
}
public IContentTypeComposition Composition { get; private set; }
public bool Allowed { get; private set; }
}
}
@@ -1,26 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Models
{
/// <summary>
/// Used when determining available compositions for a given content type
/// </summary>
internal class ContentTypeAvailableCompositionsResults
{
public ContentTypeAvailableCompositionsResults()
{
Ancestors = Enumerable.Empty<IContentTypeComposition>();
Results = Enumerable.Empty<ContentTypeAvailableCompositionsResult>();
}
public ContentTypeAvailableCompositionsResults(IEnumerable<IContentTypeComposition> ancestors, IEnumerable<ContentTypeAvailableCompositionsResult> results)
{
Ancestors = ancestors;
Results = results;
}
public IEnumerable<IContentTypeComposition> Ancestors { get; private set; }
public IEnumerable<ContentTypeAvailableCompositionsResult> Results { get; private set; }
}
}
+39 -39
View File
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Models
private string _alias;
private string _description;
private int _sortOrder;
private string _icon = "icon-folder";
private string _icon = "folder.png";
private string _thumbnail = "folder.png";
private int _creatorId;
private bool _allowedAsRoot;
@@ -373,35 +373,43 @@ namespace Umbraco.Core.Models
{
_propertyGroups = value;
_propertyGroups.CollectionChanged += PropertyGroupsChanged;
PropertyGroupsChanged(_propertyGroups, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
/// <summary>
/// Gets all property types, across all property groups.
/// List of PropertyTypes available on this ContentType.
/// This list aggregates PropertyTypes across the PropertyGroups.
/// </summary>
/// <remarks>
///
/// The setter is used purely to set the property types that DO NOT belong to a group!
///
/// Marked as DoNotClone because the result of this property is not the natural result of the data, it is
/// a union of data so when auto-cloning if the setter is used it will be setting the unnatural result of the
/// data. We manually clone this instead.
/// </remarks>
[IgnoreDataMember]
[DoNotClone]
public virtual IEnumerable<PropertyType> PropertyTypes
{
get
{
return _propertyTypes.Union(PropertyGroups.SelectMany(x => x.PropertyTypes));
var types = _propertyTypes.Union(PropertyGroups.SelectMany(x => x.PropertyTypes));
return types;
}
internal set
{
_propertyTypes = new PropertyTypeCollection(value);
_propertyTypes.CollectionChanged += PropertyTypesChanged;
}
}
/// <summary>
/// Gets or sets the property types that are not in a group.
/// Returns the property type collection containing types that are non-groups - used for tests
/// </summary>
public IEnumerable<PropertyType> NoGroupPropertyTypes
internal IEnumerable<PropertyType> NonGroupedPropertyTypes
{
get { return _propertyTypes; }
set
{
_propertyTypes = new PropertyTypeCollection(value);
_propertyTypes.CollectionChanged += PropertyTypesChanged;
PropertyTypesChanged(_propertyTypes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
/// <summary>
@@ -452,6 +460,11 @@ namespace Umbraco.Core.Models
/// <returns>Returns <c>True</c> if PropertyType was added, otherwise <c>False</c></returns>
public bool AddPropertyType(PropertyType propertyType)
{
if (propertyType.HasIdentity == false)
{
propertyType.Key = Guid.NewGuid();
}
if (PropertyTypeExists(propertyType.Alias) == false)
{
_propertyTypes.Add(propertyType);
@@ -467,37 +480,24 @@ namespace Umbraco.Core.Models
/// <param name="propertyTypeAlias">Alias of the PropertyType to move</param>
/// <param name="propertyGroupName">Name of the PropertyGroup to move the PropertyType to</param>
/// <returns></returns>
/// <remarks>If <paramref name="propertyGroupName"/> is null then the property is moved back to
/// "generic properties" ie does not have a tab anymore.</remarks>
public bool MovePropertyType(string propertyTypeAlias, string propertyGroupName)
{
// note: not dealing with alias casing at all here?
if (PropertyTypes.Any(x => x.Alias == propertyTypeAlias) == false || PropertyGroups.Any(x => x.Name == propertyGroupName) == false)
return false;
// get property, ensure it exists
var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias);
if (propertyType == null) return false;
// get new group, if required, and ensure it exists
var newPropertyGroup = propertyGroupName == null
? null
: PropertyGroups.FirstOrDefault(x => x.Name == propertyGroupName);
if (propertyGroupName != null && newPropertyGroup == null) return false;
// get old group
var oldPropertyGroup = PropertyGroups.FirstOrDefault(x =>
x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias));
// reset PropertyGroupId, which will be re-evaluated when the content type
// is saved - what is important is group.PropertyTypes - see code in
// ContentTypeBaseRepository.PersistUpdatedBaseContentType
propertyType.PropertyGroupId = new Lazy<int>(() => default(int));
propertyType.ResetDirtyProperties(); // PropertyGroupId must not be dirty
// remove from old group, if any - add to new group, if any
if (oldPropertyGroup != null)
var propertyType = PropertyTypes.First(x => x.Alias == propertyTypeAlias);
//The PropertyType already belongs to a PropertyGroup, so we have to remove the PropertyType from that group
if (PropertyGroups.Any(x => x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias)))
{
var oldPropertyGroup = PropertyGroups.First(x => x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias));
oldPropertyGroup.PropertyTypes.RemoveItem(propertyTypeAlias);
if (newPropertyGroup != null)
newPropertyGroup.PropertyTypes.Add(propertyType);
}
propertyType.PropertyGroupId = new Lazy<int>(() => default(int));
propertyType.ResetDirtyProperties();
var propertyGroup = PropertyGroups.First(x => x.Name == propertyGroupName);
propertyGroup.PropertyTypes.Add(propertyType);
return true;
}
@@ -23,8 +23,8 @@ namespace Umbraco.Core.Models
protected ContentTypeCompositionBase(IContentTypeComposition parent)
: this(parent, null)
{
}
{
}
protected ContentTypeCompositionBase(IContentTypeComposition parent, string alias)
: base(parent, alias)
@@ -37,21 +37,16 @@ namespace Umbraco.Core.Models
x => x.ContentTypeComposition);
/// <summary>
/// Gets or sets the content types that compose this content type.
/// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
[DataMember]
public IEnumerable<IContentTypeComposition> ContentTypeComposition
{
get { return _contentTypeComposition; }
set
{
_contentTypeComposition = value.ToList();
OnPropertyChanged(ContentTypeCompositionSelector);
}
}
/// <summary>
/// Gets the property groups for the entire composition.
/// Returns a list of <see cref="PropertyGroup"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyGroup> CompositionPropertyGroups
@@ -64,7 +59,7 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Gets the property types for the entire composition.
/// Returns a list of <see cref="PropertyType"/> objects from the composition
/// </summary>
[IgnoreDataMember]
public IEnumerable<PropertyType> CompositionPropertyTypes
@@ -77,10 +72,10 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Adds a content type to the composition.
/// Adds a new ContentType to the list of composite ContentTypes
/// </summary>
/// <param name="contentType">The content type to add.</param>
/// <returns>True if the content type was added, otherwise false.</returns>
/// <param name="contentType"><see cref="ContentType"/> to add</param>
/// <returns>True if ContentType was added, otherwise returns False</returns>
public bool AddContentType(IContentTypeComposition contentType)
{
if (contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
@@ -99,7 +94,13 @@ namespace Umbraco.Core.Models
.Select(p => p.Alias)).ToList();
if (conflictingPropertyTypeAliases.Any())
throw new InvalidCompositionException(Alias, contentType.Alias, conflictingPropertyTypeAliases.ToArray());
throw new InvalidCompositionException
{
AddedCompositionAlias = contentType.Alias,
ContentTypeAlias = Alias,
PropertyTypeAlias =
string.Join(", ", conflictingPropertyTypeAliases)
};
_contentTypeComposition.Add(contentType);
OnPropertyChanged(ContentTypeCompositionSelector);
@@ -109,10 +110,10 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Removes a content type with a specified alias from the composition.
/// Removes a ContentType with the supplied alias from the the list of composite ContentTypes
/// </summary>
/// <param name="alias">The alias of the content type to remove.</param>
/// <returns>True if the content type was removed, otherwise false.</returns>
/// <param name="alias">Alias of a <see cref="ContentType"/></param>
/// <returns>True if ContentType was removed, otherwise returns False</returns>
public bool RemoveContentType(string alias)
{
if (ContentTypeCompositionExists(alias))
@@ -122,10 +123,10 @@ namespace Umbraco.Core.Models
return false;
RemovedContentTypeKeyTracker.Add(contentTypeComposition.Id);
//If the ContentType we are removing has Compositions of its own these needs to be removed as well
var compositionIdsToRemove = contentTypeComposition.CompositionIds().ToList();
if (compositionIdsToRemove.Any())
if(compositionIdsToRemove.Any())
RemovedContentTypeKeyTracker.AddRange(compositionIdsToRemove);
OnPropertyChanged(ContentTypeCompositionSelector);
@@ -162,44 +163,31 @@ namespace Umbraco.Core.Models
/// <summary>
/// Adds a PropertyGroup.
/// This method will also check if a group already exists with the same name and link it to the parent.
/// </summary>
/// <param name="groupName">Name of the PropertyGroup to add</param>
/// <returns>Returns <c>True</c> if a PropertyGroup with the passed in name was added, otherwise <c>False</c></returns>
public override bool AddPropertyGroup(string groupName)
{
return AddAndReturnPropertyGroup(groupName) != null;
}
if (PropertyGroups.Any(x => x.Name == groupName))
return false;
private PropertyGroup AddAndReturnPropertyGroup(string name)
{
// ensure we don't have it already
if (PropertyGroups.Any(x => x.Name == name))
return null;
var propertyGroup = new PropertyGroup {Name = groupName, SortOrder = 0};
// create the new group
var group = new PropertyGroup { Name = name, SortOrder = 0 };
// check if it is inherited - there might be more than 1 but we want the 1st, to
// reuse its sort order - if there are more than 1 and they have different sort
// orders... there isn't much we can do anyways
var inheritGroup = CompositionPropertyGroups.FirstOrDefault(x => x.Name == name);
if (inheritGroup == null)
if (CompositionPropertyGroups.Any(x => x.Name == groupName))
{
// no, just local, set sort order
var lastGroup = PropertyGroups.LastOrDefault();
if (lastGroup != null)
group.SortOrder = lastGroup.SortOrder + 1;
}
else
{
// yes, inherited, re-use sort order
group.SortOrder = inheritGroup.SortOrder;
var firstGroup = CompositionPropertyGroups.First(x => x.Name == groupName && x.ParentId.HasValue == false);
propertyGroup.SetLazyParentId(new Lazy<int?>(() => firstGroup.Id));
}
// add
PropertyGroups.Add(group);
if (PropertyGroups.Any())
{
var last = PropertyGroups.Last();
propertyGroup.SortOrder = last.SortOrder + 1;
}
return group;
PropertyGroups.Add(propertyGroup);
return true;
}
/// <summary>
@@ -210,22 +198,39 @@ namespace Umbraco.Core.Models
/// <returns>Returns <c>True</c> if PropertyType was added, otherwise <c>False</c></returns>
public override bool AddPropertyType(PropertyType propertyType, string propertyGroupName)
{
// ensure no duplicate alias - over all composition properties
if (PropertyTypeExists(propertyType.Alias))
return false;
if (propertyType.HasIdentity == false)
{
propertyType.Key = Guid.NewGuid();
}
// get and ensure a group local to this content type
var group = PropertyGroups.Contains(propertyGroupName)
? PropertyGroups[propertyGroupName]
: AddAndReturnPropertyGroup(propertyGroupName);
if (group == null)
return false;
if (PropertyTypeExists(propertyType.Alias) == false)
{
if (PropertyGroups.Contains(propertyGroupName))
{
propertyType.PropertyGroupId = new Lazy<int>(() => PropertyGroups[propertyGroupName].Id);
PropertyGroups[propertyGroupName].PropertyTypes.Add(propertyType);
}
else
{
//If the PropertyGroup doesn't already exist we create a new one
var propertyTypes = new List<PropertyType> { propertyType };
var propertyGroup = new PropertyGroup(new PropertyTypeCollection(propertyTypes)) { Name = propertyGroupName, SortOrder = 1 };
//and check if its an inherited PropertyGroup, which exists in the composition
if (CompositionPropertyGroups.Any(x => x.Name == propertyGroupName))
{
var parentPropertyGroup = CompositionPropertyGroups.First(x => x.Name == propertyGroupName && x.ParentId.HasValue == false);
propertyGroup.SortOrder = parentPropertyGroup.SortOrder;
//propertyGroup.ParentId = parentPropertyGroup.Id;
propertyGroup.SetLazyParentId(new Lazy<int?>(() => parentPropertyGroup.Id));
}
// add property to group
propertyType.PropertyGroupId = new Lazy<int>(() => group.Id);
group.PropertyTypes.Add(propertyType);
PropertyGroups.Add(propertyGroup);
}
return true;
return true;
}
return false;
}
/// <summary>
@@ -21,8 +21,6 @@ namespace Umbraco.Core.Models
[EnumMember]
Integer,
[EnumMember]
Date,
[EnumMember]
Decimal
Date
}
}
@@ -49,6 +49,8 @@ namespace Umbraco.Core.Models
_additionalData = new Dictionary<string, object>();
}
[Obsolete("Don't use this, parentId is always -1 for data types")]
[EditorBrowsable(EditorBrowsableState.Never)]
public DataTypeDefinition(int parentId, string propertyEditorAlias)
{
_parentId = parentId;
@@ -265,5 +267,13 @@ namespace Umbraco.Core.Models
{
get { return _additionalData; }
}
internal override void AddingEntity()
{
base.AddingEntity();
if(Key == default(Guid))
Key = Guid.NewGuid();
}
}
}
+99 -61
View File
@@ -9,10 +9,30 @@ namespace Umbraco.Core.Models
{
public static class DeepCloneHelper
{
/// <summary>
/// Stores the metadata for the properties for a given type so we know how to create them
/// </summary>
private struct ClonePropertyInfo
{
public ClonePropertyInfo(PropertyInfo propertyInfo) : this()
{
if (propertyInfo == null) throw new ArgumentNullException("propertyInfo");
PropertyInfo = propertyInfo;
}
public PropertyInfo PropertyInfo { get; private set; }
public bool IsDeepCloneable { get; set; }
public Type GenericListType { get; set; }
public bool IsList
{
get { return GenericListType != null; }
}
}
/// <summary>
/// Used to avoid constant reflection (perf)
/// </summary>
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropCache = new ConcurrentDictionary<Type, PropertyInfo[]>();
private static readonly ConcurrentDictionary<Type, ClonePropertyInfo[]> PropCache = new ConcurrentDictionary<Type, ClonePropertyInfo[]>();
/// <summary>
/// Used to deep clone any reference properties on the object (should be done after a MemberwiseClone for which the outcome is 'output')
@@ -30,81 +50,99 @@ namespace Umbraco.Core.Models
throw new InvalidOperationException("Both the input and output types must be the same");
}
//get the property metadata from cache so we only have to figure this out once per type
var refProperties = PropCache.GetOrAdd(inputType, type =>
inputType.GetProperties()
.Where(x =>
//is not attributed with the ignore clone attribute
x.GetCustomAttribute<DoNotCloneAttribute>() == null
.Select<PropertyInfo, ClonePropertyInfo?>(propertyInfo =>
{
if (
//is not attributed with the ignore clone attribute
propertyInfo.GetCustomAttribute<DoNotCloneAttribute>() != null
//reference type but not string
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|| propertyInfo.PropertyType.IsValueType || propertyInfo.PropertyType == typeof (string)
//settable
&& x.CanWrite
|| propertyInfo.CanWrite == false
//non-indexed
&& x.GetIndexParameters().Any() == false)
|| propertyInfo.GetIndexParameters().Any())
{
return null;
}
if (TypeHelper.IsTypeAssignableFrom<IDeepCloneable>(propertyInfo.PropertyType))
{
return new ClonePropertyInfo(propertyInfo) { IsDeepCloneable = true };
}
if (TypeHelper.IsTypeAssignableFrom<IEnumerable>(propertyInfo.PropertyType)
&& TypeHelper.IsTypeAssignableFrom<string>(propertyInfo.PropertyType) == false)
{
if (propertyInfo.PropertyType.IsGenericType
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
return new ClonePropertyInfo(propertyInfo) { GenericListType = genericType };
}
if (propertyInfo.PropertyType.IsArray
|| (propertyInfo.PropertyType.IsInterface && propertyInfo.PropertyType.IsGenericType == false))
{
//if its an array, we'll create a list to work with first and then convert to array later
//otherwise if its just a regular derivitave of IEnumerable, we can use a list too
return new ClonePropertyInfo(propertyInfo) { GenericListType = typeof(List<object>) };
}
//skip instead of trying to create instance of abstract or interface
if (propertyInfo.PropertyType.IsAbstract || propertyInfo.PropertyType.IsInterface)
{
return null;
}
//its a custom IEnumerable, we'll try to create it
try
{
var custom = Activator.CreateInstance(propertyInfo.PropertyType);
//if it's an IList we can work with it, otherwise we cannot
var newList = custom as IList;
if (newList == null)
{
return null;
}
return new ClonePropertyInfo(propertyInfo) {GenericListType = propertyInfo.PropertyType};
}
catch (Exception)
{
//could not create this type so we'll skip it
return null;
}
}
return new ClonePropertyInfo(propertyInfo);
})
.Where(x => x.HasValue)
.Select(x => x.Value)
.ToArray());
foreach (var propertyInfo in refProperties)
foreach (var clonePropertyInfo in refProperties)
{
if (TypeHelper.IsTypeAssignableFrom<IDeepCloneable>(propertyInfo.PropertyType))
if (clonePropertyInfo.IsDeepCloneable)
{
//this ref property is also deep cloneable so clone it
var result = (IDeepCloneable)propertyInfo.GetValue(input, null);
var result = (IDeepCloneable)clonePropertyInfo.PropertyInfo.GetValue(input, null);
if (result != null)
{
//set the cloned value to the property
propertyInfo.SetValue(output, result.DeepClone(), null);
clonePropertyInfo.PropertyInfo.SetValue(output, result.DeepClone(), null);
}
}
else if (TypeHelper.IsTypeAssignableFrom<IEnumerable>(propertyInfo.PropertyType)
&& TypeHelper.IsTypeAssignableFrom<string>(propertyInfo.PropertyType) == false)
else if (clonePropertyInfo.IsList)
{
IList newList;
if (propertyInfo.PropertyType.IsGenericType
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
newList = (IList)Activator.CreateInstance(genericType);
}
else if (propertyInfo.PropertyType.IsArray
|| (propertyInfo.PropertyType.IsInterface && propertyInfo.PropertyType.IsGenericType == false))
{
//if its an array, we'll create a list to work with first and then convert to array later
//otherwise if its just a regular derivitave of IEnumerable, we can use a list too
newList = new List<object>();
}
else
{
//skip instead of trying to create instance of abstract or interface
if (propertyInfo.PropertyType.IsAbstract || propertyInfo.PropertyType.IsInterface)
{
continue;
}
//its a custom IEnumerable, we'll try to create it
try
{
var custom = Activator.CreateInstance(propertyInfo.PropertyType);
//if it's an IList we can work with it, otherwise we cannot
newList = custom as IList;
if (newList == null)
{
continue;
}
}
catch (Exception)
{
//could not create this type so we'll skip it
continue;
}
}
var enumerable = (IEnumerable)propertyInfo.GetValue(input, null);
var enumerable = (IEnumerable)clonePropertyInfo.PropertyInfo.GetValue(input, null);
if (enumerable == null) continue;
var newList = (IList)Activator.CreateInstance(clonePropertyInfo.GenericListType);
var isUsableType = true;
//now clone each item
@@ -136,21 +174,21 @@ namespace Umbraco.Core.Models
continue;
}
if (propertyInfo.PropertyType.IsArray)
if (clonePropertyInfo.PropertyInfo.PropertyType.IsArray)
{
//need to convert to array
var arr = (object[])Activator.CreateInstance(propertyInfo.PropertyType, newList.Count);
var arr = (object[])Activator.CreateInstance(clonePropertyInfo.PropertyInfo.PropertyType, newList.Count);
for (int i = 0; i < newList.Count; i++)
{
arr[i] = newList[i];
}
//set the cloned collection
propertyInfo.SetValue(output, arr, null);
clonePropertyInfo.PropertyInfo.SetValue(output, arr, null);
}
else
{
//set the cloned collection
propertyInfo.SetValue(output, newList, null);
clonePropertyInfo.PropertyInfo.SetValue(output, newList, null);
}
}
+11
View File
@@ -98,5 +98,16 @@ namespace Umbraco.Core.Models
enumerable => enumerable.GetHashCode()));
}
}
/// <summary>
/// Method to call before inserting a new entity in the db
/// </summary>
internal override void AddingEntity()
{
base.AddingEntity();
Key = Guid.NewGuid();
}
}
}
+2 -4
View File
@@ -62,9 +62,9 @@ namespace Umbraco.Core.Models.EntityBase
{
get
{
// if an entity does NOT have a UniqueId yet, assign one now
if (_key == Guid.Empty)
_key = Guid.NewGuid();
return _id.ToGuid();
return _key;
}
set
@@ -136,7 +136,6 @@ namespace Umbraco.Core.Models.EntityBase
{
_hasIdentity = false;
_id = default(int);
_key = Guid.Empty;
}
/// <summary>
@@ -243,7 +242,6 @@ namespace Umbraco.Core.Models.EntityBase
{
//Memberwise clone on Entity will work since it doesn't have any deep elements
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
var ignored = this.Key; // ensure that 'this' has a key, before cloning
var clone = (Entity)MemberwiseClone();
//ensure the clone has it's own dictionaries
clone.ResetChangeTrackingCollections();
@@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a folder for organizing entities such as content types and data types.
/// </summary>
public sealed class EntityContainer : UmbracoEntity
{
private readonly Guid _containedObjectType;
private static readonly Dictionary<Guid, Guid> ObjectTypeMap = new Dictionary<Guid, Guid>
{
{ Constants.ObjectTypes.DataTypeGuid, Constants.ObjectTypes.DataTypeContainerGuid },
{ Constants.ObjectTypes.DocumentTypeGuid, Constants.ObjectTypes.DocumentTypeContainerGuid },
{ Constants.ObjectTypes.MediaTypeGuid, Constants.ObjectTypes.MediaTypeContainerGuid }
};
/// <summary>
/// Initializes a new instance of an <see cref="EntityContainer"/> class.
/// </summary>
public EntityContainer(Guid containedObjectType)
{
if (ObjectTypeMap.ContainsKey(containedObjectType) == false)
throw new ArgumentException("Not a contained object type.", "containedObjectType");
_containedObjectType = containedObjectType;
ParentId = -1;
Path = "-1";
Level = 0;
SortOrder = 0;
}
/// <summary>
/// Initializes a new instance of an <see cref="EntityContainer"/> class.
/// </summary>
internal EntityContainer(int id, Guid uniqueId, int parentId, string path, int level, int sortOrder, Guid containedObjectType, string name, int userId)
: this(containedObjectType)
{
Id = id;
Key = uniqueId;
ParentId = parentId;
Name = name;
Path = path;
Level = level;
SortOrder = sortOrder;
CreatorId = userId;
}
/// <summary>
/// Gets or sets the node object type of the contained objects.
/// </summary>
public Guid ContainedObjectType
{
get { return _containedObjectType; }
}
/// <summary>
/// Gets the node object type of the container objects.
/// </summary>
public Guid ContainerObjectType
{
get { return ObjectTypeMap[_containedObjectType]; }
}
/// <summary>
/// Gets the container object type corresponding to a contained object type.
/// </summary>
/// <param name="containedObjectType">The contained object type.</param>
/// <returns>The object type of containers containing objects of the contained object type.</returns>
public static Guid GetContainerObjectType(Guid containedObjectType)
{
if (ObjectTypeMap.ContainsKey(containedObjectType) == false)
throw new ArgumentException("Not a contained object type.", "containedObjectType");
return ObjectTypeMap[containedObjectType];
}
/// <summary>
/// Gets the contained object type corresponding to a container object type.
/// </summary>
/// <param name="containerObjectType">The container object type.</param>
/// <returns>The object type of objects that containers of the container object type can contain.</returns>
public static Guid GetContainedObjectType(Guid containerObjectType)
{
var contained = ObjectTypeMap.FirstOrDefault(x => x.Value == containerObjectType).Key;
if (contained == null)
throw new ArgumentException("Not a container object type.", "containerObjectType");
return contained;
}
}
}
+1 -6
View File
@@ -54,15 +54,10 @@ namespace Umbraco.Core.Models
PropertyGroupCollection PropertyGroups { get; set; }
/// <summary>
/// Gets all property types, across all property groups.
/// Gets an enumerable list of Property Types aggregated for all groups
/// </summary>
IEnumerable<PropertyType> PropertyTypes { get; }
/// <summary>
/// Gets or sets the property types that are not in a group.
/// </summary>
IEnumerable<PropertyType> NoGroupPropertyTypes { get; set; }
/// <summary>
/// Removes a PropertyType from the current ContentType
/// </summary>
@@ -8,17 +8,17 @@ namespace Umbraco.Core.Models
public interface IContentTypeComposition : IContentTypeBase
{
/// <summary>
/// Gets or sets the content types that compose this content type.
/// Gets a list of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
/// </summary>
IEnumerable<IContentTypeComposition> ContentTypeComposition { get; set; }
IEnumerable<IContentTypeComposition> ContentTypeComposition { get; }
/// <summary>
/// Gets the property groups for the entire composition.
/// Gets a list of <see cref="PropertyGroup"/> objects from the composition
/// </summary>
IEnumerable<PropertyGroup> CompositionPropertyGroups { get; }
/// <summary>
/// Gets the property types for the entire composition.
/// Gets a list of <see cref="PropertyType"/> objects from the composition
/// </summary>
IEnumerable<PropertyType> CompositionPropertyTypes { get; }
@@ -1,20 +0,0 @@
using AutoMapper;
namespace Umbraco.Core.Models.Mapping
{
internal static class MappingExpressionExtensions
{
/// <summary>
/// Ignores all unmapped members by default - Use with caution!
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TDest"></typeparam>
/// <param name="expression"></param>
/// <returns></returns>
public static IMappingExpression<TSource, TDest> IgnoreAllUnmapped<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
{
expression.ForAllMembers(opt => opt.Ignore());
return expression;
}
}
}
+12
View File
@@ -118,5 +118,17 @@ namespace Umbraco.Core.Models
//The Media Recycle Bin Id is -21 so we correct that here
ParentId = parentId == -20 ? -21 : parentId;
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
}
}
+21
View File
@@ -38,5 +38,26 @@ namespace Umbraco.Core.Models
: base(parent, alias)
{
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
/// <summary>
/// Method to call when Entity is being updated
/// </summary>
/// <remarks>Modified Date is set and a new Version guid is set</remarks>
internal override void UpdatingEntity()
{
base.UpdatingEntity();
}
}
}
+4 -1
View File
@@ -509,8 +509,11 @@ namespace Umbraco.Core.Models
{
base.AddingEntity();
if (ProviderUserKey == null)
if (Key == Guid.Empty)
{
Key = Guid.NewGuid();
ProviderUserKey = Key;
}
}
/// <summary>
+12
View File
@@ -60,5 +60,17 @@ namespace Umbraco.Core.Models
}
public IDictionary<string, object> AdditionalData { get; private set; }
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
}
}
+21
View File
@@ -131,5 +131,26 @@ namespace Umbraco.Core.Models
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
/// <summary>
/// Method to call when Entity is being updated
/// </summary>
/// <remarks>Modified Date is set and a new Version guid is set</remarks>
internal override void UpdatingEntity()
{
base.UpdatingEntity();
}
}
}
+34
View File
@@ -17,6 +17,7 @@ namespace Umbraco.Core.Models
public class PropertyGroup : Entity, IEquatable<PropertyGroup>
{
private string _name;
private Lazy<int?> _parentId;
private int _sortOrder;
private PropertyTypeCollection _propertyTypes;
@@ -30,6 +31,7 @@ namespace Umbraco.Core.Models
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, int?>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, int>(x => x.SortOrder);
private readonly static PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo<PropertyGroup, PropertyTypeCollection>(x => x.PropertyTypes);
void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e)
@@ -54,6 +56,29 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Gets or sets the Id of the Parent PropertyGroup.
/// </summary>
/// <remarks>
/// A Parent PropertyGroup corresponds to an inherited PropertyGroup from a composition.
/// If a PropertyType is inserted into an inherited group then a new group will be created with an Id reference to the parent.
/// </remarks>
[DataMember]
public int? ParentId
{
get
{
if (_parentId == null)
return default(int?);
return _parentId.Value;
}
set
{
_parentId = new Lazy<int?>(() => value);
OnPropertyChanged(ParentIdSelector);
}
}
/// <summary>
/// Gets or sets the Sort Order of the Group
/// </summary>
@@ -92,6 +117,15 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Sets the ParentId from the lazy integer id
/// </summary>
/// <param name="id">Id of the Parent</param>
internal void SetLazyParentId(Lazy<int?> id)
{
_parentId = id;
}
public bool Equals(PropertyGroup other)
{
if (base.Equals(other)) return true;
-6
View File
@@ -9,7 +9,6 @@ using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
{
/// <summary>
/// Defines the type of a <see cref="Property"/> object
/// </summary>
@@ -33,8 +32,6 @@ namespace Umbraco.Core.Models
public PropertyType(IDataTypeDefinition dataTypeDefinition)
{
if (dataTypeDefinition == null) throw new ArgumentNullException("dataTypeDefinition");
if(dataTypeDefinition.HasIdentity)
_dataTypeDefinitionId = dataTypeDefinition.Id;
@@ -404,9 +401,6 @@ namespace Umbraco.Core.Models
if (DataTypeDatabaseType == DataTypeDatabaseType.Integer && type == typeof(int))
return true;
if (DataTypeDatabaseType == DataTypeDatabaseType.Decimal && type == typeof(decimal))
return true;
if (DataTypeDatabaseType == DataTypeDatabaseType.Date && type == typeof(DateTime))
return true;
@@ -108,6 +108,18 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Method to call on entity saved when first added
/// </summary>
internal override void AddingEntity()
{
if (Key == default(Guid))
{
Key = Guid.NewGuid();
}
base.AddingEntity();
}
[DataMember]
public int LoginNodeId
{
@@ -28,6 +28,18 @@ namespace Umbraco.Core.Models
public Guid AccessEntryId { get; internal set; }
/// <summary>
/// Method to call on entity saved when first added
/// </summary>
internal override void AddingEntity()
{
if (Key == default(Guid))
{
Key = Guid.NewGuid();
}
base.AddingEntity();
}
public string RuleValue
{
get { return _ruleValue; }
@@ -230,13 +230,13 @@ namespace Umbraco.Core.Models.PublishedContent
{
_sourceCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.Source);
_objectCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.Object);
_objectCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.XPath);
_xpathCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.XPath);
}
else
{
_sourceCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.Source);
_objectCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.Object);
_objectCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.XPath);
_xpathCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.XPath);
}
if (_objectCacheLevel < _sourceCacheLevel) _objectCacheLevel = _sourceCacheLevel;
if (_xpathCacheLevel < _sourceCacheLevel) _xpathCacheLevel = _sourceCacheLevel;
@@ -1,28 +1,28 @@
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("cmsDocumentType")]
[PrimaryKey("contentTypeNodeId", autoIncrement = false)]
[ExplicitColumns]
internal class ContentTypeTemplateDto
{
[Column("contentTypeNodeId")]
[PrimaryKeyColumn(AutoIncrement = false, Name = "PK_cmsDocumentType", OnColumns = "contentTypeNodeId, templateNodeId")]
[ForeignKey(typeof(ContentTypeDto), Column = "nodeId")]
[ForeignKey(typeof(NodeDto))]
public int ContentTypeNodeId { get; set; }
[Column("templateNodeId")]
[ForeignKey(typeof(TemplateDto), Column = "nodeId")]
public int TemplateNodeId { get; set; }
[Column("IsDefault")]
[Constraint(Default = "0")]
public bool IsDefault { get; set; }
[ResultColumn]
public ContentTypeDto ContentTypeDto { get; set; }
}
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("cmsDocumentType")]
[PrimaryKey("contentTypeNodeId", autoIncrement = false)]
[ExplicitColumns]
internal class DocumentTypeDto
{
[Column("contentTypeNodeId")]
[PrimaryKeyColumn(AutoIncrement = false, Name = "PK_cmsDocumentType", OnColumns = "contentTypeNodeId, templateNodeId")]
[ForeignKey(typeof(ContentTypeDto), Column = "nodeId")]
[ForeignKey(typeof(NodeDto))]
public int ContentTypeNodeId { get; set; }
[Column("templateNodeId")]
[ForeignKey(typeof(TemplateDto), Column = "nodeId")]
public int TemplateNodeId { get; set; }
[Column("IsDefault")]
[Constraint(Default = "0")]
public bool IsDefault { get; set; }
[ResultColumn]
public ContentTypeDto ContentTypeDto { get; set; }
}
}
+6
View File
@@ -10,6 +10,12 @@ namespace Umbraco.Core.Models.Rdbms
[ExplicitColumns]
internal class NodeDto
{
public NodeDto()
{
//By default, always generate a new guid
UniqueId = Guid.NewGuid();
}
public const int NodeIdSeed = 1050;
[Column("id")]
@@ -33,10 +33,6 @@ namespace Umbraco.Core.Models.Rdbms
[NullSetting(NullSetting = NullSettings.Null)]
public int? Integer { get; set; }
[Column("dataDecimal")]
[NullSetting(NullSetting = NullSettings.Null)]
public decimal? Decimal { get; set; }
[Column("dataDate")]
[NullSetting(NullSetting = NullSettings.Null)]
public DateTime? Date { get; set; }
@@ -59,27 +55,22 @@ namespace Umbraco.Core.Models.Rdbms
{
get
{
if (Integer.HasValue)
if(Integer.HasValue)
{
return Integer.Value;
}
if (Decimal.HasValue)
{
return Decimal.Value;
}
if (Date.HasValue)
if(Date.HasValue)
{
return Date.Value;
}
if (string.IsNullOrEmpty(VarChar) == false)
if(string.IsNullOrEmpty(VarChar) == false)
{
return VarChar;
}
if (string.IsNullOrEmpty(Text) == false)
if(string.IsNullOrEmpty(Text) == false)
{
return Text;
}
@@ -10,6 +10,12 @@ namespace Umbraco.Core.Models.Rdbms
[ExplicitColumns]
internal class PropertyTypeDto
{
public PropertyTypeDto()
{
//by default always create a new guid
UniqueId = Guid.NewGuid();
}
[Column("id")]
[PrimaryKeyColumn(IdentitySeed = 50)]
public int Id { get; set; }
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
@@ -15,6 +13,12 @@ namespace Umbraco.Core.Models.Rdbms
[PrimaryKeyColumn(IdentitySeed = 12)]
public int Id { get; set; }
[Column("parentGroupId")]
[NullSetting(NullSetting = NullSettings.Null)]
//[Constraint(Default = "NULL")]
[ForeignKey(typeof(PropertyTypeGroupDto))]
public int? ParentGroupId { get; set; }
[Column("contenttypeNodeId")]
[ForeignKey(typeof(ContentTypeDto), Column = "nodeId")]
public int ContentTypeNodeId { get; set; }
@@ -27,11 +31,5 @@ namespace Umbraco.Core.Models.Rdbms
[ResultColumn]
public List<PropertyTypeDto> PropertyTypeDtos { get; set; }
[Column("uniqueID")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Constraint(Default = SystemMethods.NewGuid)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyTypeGroupUniqueID")]
public Guid UniqueId { get; set; }
}
}
@@ -10,6 +10,9 @@ namespace Umbraco.Core.Models.Rdbms
[Column("PropertyTypeGroupId")]
public int? Id { get; set; }
[Column("parentGroupId")]
public int? ParentGroupId { get; set; }
[Column("PropertyGroupName")]
public string Text { get; set; }
@@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoDeployChecksum")]
[PrimaryKey("id")]
[ExplicitColumns]
internal class UmbracoDeployChecksumDto
{
[Column("id")]
[PrimaryKeyColumn(Name = "PK_umbracoDeployChecksum")]
public int Id { get; set; }
[Column("entityType")]
[Length(32)]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoDeployChecksum", ForColumns = "entityType,entityGuid,entityPath")]
public string EntityType { get; set; }
[Column("entityGuid")]
[NullSetting(NullSetting = NullSettings.Null)]
public Guid EntityGuid { get; set; }
[Column("entityPath")]
[Length(256)]
[NullSetting(NullSetting = NullSettings.Null)]
public string EntityPath { get; set; }
[Column("localChecksum")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Length(32)]
public string LocalChecksum { get; set; }
[Column("compositeChecksum")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(32)]
public string CompositeChecksum { get; set; }
}
}
@@ -1,26 +0,0 @@
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoDeployDependency")]
[ExplicitColumns]
internal class UmbracoDeployDependencyDto
{
[Column("sourceId")]
[PrimaryKeyColumn(AutoIncrement = false, Clustered = true, Name = "PK_umbracoDeployDependency", OnColumns = "sourceId, targetId")]
[ForeignKey(typeof(UmbracoDeployChecksumDto), Name = "FK_umbracoDeployDependency_umbracoDeployChecksum_id1")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int SourceId { get; set; }
[Column("targetId")]
[ForeignKey(typeof(UmbracoDeployChecksumDto), Name = "FK_umbracoDeployDependency_umbracoDeployChecksum_id2")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int TargetId { get; set; }
[Column("mode")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int Mode { get; set; }
}
}
+12
View File
@@ -118,6 +118,18 @@ namespace Umbraco.Core.Models
return ApplicationContext.Current.Services.FileService.DetermineTemplateRenderingEngine(this);
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
public void SetMasterTemplate(ITemplate masterTemplate)
{
if (masterTemplate == null)
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Implementation of the <see cref="IUmbracoEntity"/> for internal use.
/// </summary>
public class UmbracoEntity : Entity, IUmbracoEntity
internal class UmbracoEntity : Entity, IUmbracoEntity
{
private int _creatorId;
private int _level;
@@ -11,20 +11,6 @@ namespace Umbraco.Core.Models
internal static class UmbracoEntityExtensions
{
public static bool HasChildren(this IUmbracoEntity entity)
{
if (entity.AdditionalData.ContainsKey("HasChildren"))
{
var convert = entity.AdditionalData["HasChildren"].TryConvertTo<bool>();
if (convert)
{
return convert.Result;
}
}
return false;
}
public static object GetAdditionalDataValueIgnoreCase(this IUmbracoEntity entity, string key, object defaultVal)
{
if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultVal;
+15 -38
View File
@@ -15,49 +15,49 @@ namespace Umbraco.Core.Models
/// <summary>
/// Content Item Type
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.ContentItemType)]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.ContentItemType)]
[FriendlyName("Content Item Type")]
ContentItemType,
/// <summary>
/// Root
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.SystemRoot)]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.SystemRoot)]
[FriendlyName("Root")]
ROOT,
/// <summary>
/// Document
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Document, typeof(IContent))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.Document, typeof(IContent))]
[FriendlyName("Document")]
Document,
/// <summary>
/// Media
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Media, typeof(IMedia))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.Media, typeof(IMedia))]
[FriendlyName("Media")]
Media,
/// <summary>
/// Member Type
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.MemberType, typeof(IMemberType))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.MemberType, typeof(IMemberType))]
[FriendlyName("Member Type")]
MemberType,
/// <summary>
/// Template
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Template, typeof(ITemplate))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.Template, typeof(ITemplate))]
[FriendlyName("Template")]
Template,
/// <summary>
/// Member Group
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.MemberGroup)]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.MemberGroup)]
[FriendlyName("Member Group")]
MemberGroup,
@@ -65,73 +65,50 @@ namespace Umbraco.Core.Models
/// <summary>
/// Content Item
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.ContentItem)]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.ContentItem)]
[FriendlyName("Content Item")]
ContentItem,
/// <summary>
/// "Media Type
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.MediaType, typeof(IMediaType))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.MediaType, typeof(IMediaType))]
[FriendlyName("Media Type")]
MediaType,
/// <summary>
/// Document Type
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DocumentType, typeof(IContentType))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.DocumentType, typeof(IContentType))]
[FriendlyName("Document Type")]
DocumentType,
/// <summary>
/// Recycle Bin
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.ContentRecycleBin)]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.ContentRecycleBin)]
[FriendlyName("Recycle Bin")]
RecycleBin,
/// <summary>
/// Stylesheet
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Stylesheet)]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.Stylesheet)]
[FriendlyName("Stylesheet")]
Stylesheet,
/// <summary>
/// Member
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.Member, typeof(IMember))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.Member, typeof(IMember))]
[FriendlyName("Member")]
Member,
/// <summary>
/// Data Type
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DataType, typeof(IDataTypeDefinition))]
[UmbracoObjectTypeAttribute(Constants.ObjectTypes.DataType, typeof(IDataTypeDefinition))]
[FriendlyName("Data Type")]
DataType,
/// <summary>
/// Document type container
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DocumentTypeContainer)]
[FriendlyName("Document Type Container")]
DocumentTypeContainer,
/// <summary>
/// Media type container
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.MediaTypeContainer)]
[FriendlyName("Media Type Container")]
MediaTypeContainer,
/// <summary>
/// Media type container
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DataTypeContainer)]
[FriendlyName("Data Type Container")]
DataTypeContainer
DataType
}
}
@@ -1,144 +1,98 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
// factory for
// IContentType (document types)
// IMediaType (media types)
// IMemberType (member types)
//
internal class ContentTypeFactory
{
#region IContentType
private readonly Guid _nodeObjectType;
public IContentType BuildContentTypeEntity(ContentTypeDto dto)
public ContentTypeFactory(Guid nodeObjectType)
{
var contentType = new ContentType(dto.NodeDto.ParentId);
BuildCommonEntity(contentType, dto);
_nodeObjectType = nodeObjectType;
}
#region Implementation of IEntityFactory<IContentType,DocumentTypeDto>
public IContentType BuildEntity(DocumentTypeDto dto)
{
var contentType = new ContentType(dto.ContentTypeDto.NodeDto.ParentId)
{
Id = dto.ContentTypeDto.NodeDto.NodeId,
Key = dto.ContentTypeDto.NodeDto.UniqueId,
Alias = dto.ContentTypeDto.Alias,
Name = dto.ContentTypeDto.NodeDto.Text,
Icon = dto.ContentTypeDto.Icon,
Thumbnail = dto.ContentTypeDto.Thumbnail,
SortOrder = dto.ContentTypeDto.NodeDto.SortOrder,
Description = dto.ContentTypeDto.Description,
CreateDate = dto.ContentTypeDto.NodeDto.CreateDate,
Path = dto.ContentTypeDto.NodeDto.Path,
Level = dto.ContentTypeDto.NodeDto.Level,
CreatorId = dto.ContentTypeDto.NodeDto.UserId.Value,
AllowedAsRoot = dto.ContentTypeDto.AllowAtRoot,
IsContainer = dto.ContentTypeDto.IsContainer,
Trashed = dto.ContentTypeDto.NodeDto.Trashed,
DefaultTemplateId = dto.TemplateNodeId
};
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
contentType.ResetDirtyProperties(false);
return contentType;
}
#endregion
#region IMediaType
public IMediaType BuildMediaTypeEntity(ContentTypeDto dto)
public DocumentTypeDto BuildDto(IContentType entity)
{
var contentType = new MediaType(dto.NodeDto.ParentId);
BuildCommonEntity(contentType, dto);
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
contentType.ResetDirtyProperties(false);
return contentType;
}
#endregion
#region IMemberType
public IMemberType BuildMemberTypeEntity(ContentTypeDto dto)
{
throw new NotImplementedException();
}
public IEnumerable<MemberTypeDto> BuildMemberTypeDtos(IMemberType entity)
{
var memberType = entity as MemberType;
if (memberType == null || memberType.PropertyTypes.Any() == false)
return Enumerable.Empty<MemberTypeDto>();
var dtos = memberType.PropertyTypes.Select(x => new MemberTypeDto
var documentTypeDto = new DocumentTypeDto
{ContentTypeDto = BuildContentTypeDto(entity), ContentTypeNodeId = entity.Id};
var contentType = entity as ContentType;
if(contentType != null)
{
NodeId = entity.Id,
PropertyTypeId = x.Id,
CanEdit = memberType.MemberCanEditProperty(x.Alias),
ViewOnProfile = memberType.MemberCanViewProperty(x.Alias)
}).ToList();
return dtos;
documentTypeDto.TemplateNodeId = contentType.DefaultTemplateId;
documentTypeDto.IsDefault = true;
}
return documentTypeDto;
}
#endregion
#region Common
private static void BuildCommonEntity(ContentTypeBase entity, ContentTypeDto dto)
private ContentTypeDto BuildContentTypeDto(IContentType entity)
{
entity.Id = dto.NodeDto.NodeId;
entity.Key = dto.NodeDto.UniqueId;
entity.Alias = dto.Alias;
entity.Name = dto.NodeDto.Text;
entity.Icon = dto.Icon;
entity.Thumbnail = dto.Thumbnail;
entity.SortOrder = dto.NodeDto.SortOrder;
entity.Description = dto.Description;
entity.CreateDate = dto.NodeDto.CreateDate;
entity.Path = dto.NodeDto.Path;
entity.Level = dto.NodeDto.Level;
entity.CreatorId = dto.NodeDto.UserId.Value;
entity.AllowedAsRoot = dto.AllowAtRoot;
entity.IsContainer = dto.IsContainer;
entity.Trashed = dto.NodeDto.Trashed;
}
public ContentTypeDto BuildContentTypeDto(IContentTypeBase entity)
{
Guid nodeObjectType;
if (entity is IContentType)
nodeObjectType = Constants.ObjectTypes.DocumentTypeGuid;
else if (entity is IMediaType)
nodeObjectType = Constants.ObjectTypes.MediaTypeGuid;
else if (entity is IMemberType)
nodeObjectType = Constants.ObjectTypes.MemberTypeGuid;
else
throw new Exception("oops: invalid entity.");
var contentTypeDto = new ContentTypeDto
{
Alias = entity.Alias,
Description = entity.Description,
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
NodeDto = BuildNodeDto(entity, nodeObjectType)
};
{
Alias = entity.Alias,
Description = entity.Description,
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
NodeDto = BuildNodeDto(entity)
};
return contentTypeDto;
}
private static NodeDto BuildNodeDto(IUmbracoEntity entity, Guid nodeObjectType)
private NodeDto BuildNodeDto(IContentType entity)
{
var nodeDto = new NodeDto
{
CreateDate = entity.CreateDate,
NodeId = entity.Id,
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
NodeObjectType = nodeObjectType,
ParentId = entity.ParentId,
Path = entity.Path,
SortOrder = entity.SortOrder,
Text = entity.Name,
Trashed = false,
UniqueId = entity.Key,
UserId = entity.CreatorId
};
{
CreateDate = entity.CreateDate,
NodeId = entity.Id,
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
NodeObjectType = _nodeObjectType,
ParentId = entity.ParentId,
Path = entity.Path,
SortOrder = entity.SortOrder,
Text = entity.Name,
Trashed = false,
UniqueId = entity.Key,
UserId = entity.CreatorId
};
return nodeDto;
}
#endregion
}
}
@@ -0,0 +1,82 @@
using System;
using System.Globalization;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal class MediaTypeFactory
{
private readonly Guid _nodeObjectType;
public MediaTypeFactory(Guid nodeObjectType)
{
_nodeObjectType = nodeObjectType;
}
#region Implementation of IEntityFactory<IMediaType,ContentTypeDto>
public IMediaType BuildEntity(ContentTypeDto dto)
{
var contentType = new MediaType(dto.NodeDto.ParentId)
{
Id = dto.NodeDto.NodeId,
Key = dto.NodeDto.UniqueId,
Alias = dto.Alias,
Name = dto.NodeDto.Text,
Icon = dto.Icon,
Thumbnail = dto.Thumbnail,
SortOrder = dto.NodeDto.SortOrder,
Description = dto.Description,
CreateDate = dto.NodeDto.CreateDate,
Path = dto.NodeDto.Path,
Level = dto.NodeDto.Level,
CreatorId = dto.NodeDto.UserId.Value,
AllowedAsRoot = dto.AllowAtRoot,
IsContainer = dto.IsContainer,
Trashed = dto.NodeDto.Trashed
};
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
contentType.ResetDirtyProperties(false);
return contentType;
}
public ContentTypeDto BuildDto(IMediaType entity)
{
var contentTypeDto = new ContentTypeDto
{
Alias = entity.Alias,
Description = entity.Description,
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
NodeDto = BuildNodeDto(entity)
};
return contentTypeDto;
}
#endregion
private NodeDto BuildNodeDto(IMediaType entity)
{
var nodeDto = new NodeDto
{
CreateDate = entity.CreateDate,
NodeId = entity.Id,
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
NodeObjectType = _nodeObjectType,
ParentId = entity.ParentId,
Path = entity.Path,
SortOrder = entity.SortOrder,
Text = entity.Name,
Trashed = false,
UniqueId = entity.Key,
UserId = entity.CreatorId
};
return nodeDto;
}
}
}
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal class MemberTypeFactory
{
private readonly Guid _nodeObjectType;
public MemberTypeFactory(Guid nodeObjectType)
{
_nodeObjectType = nodeObjectType;
}
public IMemberType BuildEntity(ContentTypeDto dto)
{
throw new System.NotImplementedException();
}
public ContentTypeDto BuildDto(IMemberType entity)
{
var contentTypeDto = new ContentTypeDto
{
Alias = entity.Alias,
Description = entity.Description,
Icon = entity.Icon,
Thumbnail = entity.Thumbnail,
NodeId = entity.Id,
AllowAtRoot = entity.AllowedAsRoot,
IsContainer = entity.IsContainer,
NodeDto = BuildNodeDto(entity)
};
return contentTypeDto;
}
public IEnumerable<MemberTypeDto> BuildMemberTypeDtos(IMemberType entity)
{
var memberType = entity as MemberType;
if (memberType == null || memberType.PropertyTypes.Any() == false)
return Enumerable.Empty<MemberTypeDto>();
var memberTypes = new List<MemberTypeDto>();
foreach (var propertyType in memberType.PropertyTypes)
{
memberTypes.Add(new MemberTypeDto
{
NodeId = entity.Id,
PropertyTypeId = propertyType.Id,
CanEdit = memberType.MemberCanEditProperty(propertyType.Alias),
ViewOnProfile = memberType.MemberCanViewProperty(propertyType.Alias)
});
}
return memberTypes;
}
private NodeDto BuildNodeDto(IMemberType entity)
{
var nodeDto = new NodeDto
{
CreateDate = entity.CreateDate,
NodeId = entity.Id,
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
NodeObjectType = _nodeObjectType,
ParentId = entity.ParentId,
Path = entity.Path,
SortOrder = entity.SortOrder,
Text = entity.Name,
Trashed = false,
UniqueId = entity.Key,
UserId = entity.CreatorId
};
return nodeDto;
}
private int DeterminePropertyTypeId(int initialId, string alias, IEnumerable<PropertyType> propertyTypes)
{
if (initialId == 0 || initialId == default(int))
{
var propertyType = propertyTypes.SingleOrDefault(x => x.Alias.Equals(alias));
if (propertyType == null)
return default(int);
return propertyType.Id;
}
return initialId;
}
}
}
@@ -51,28 +51,31 @@ namespace Umbraco.Core.Persistence.Factories
memberType.MemberTypePropertyTypes.Add(standardPropertyType.Key,
new MemberTypePropertyProfileAccess(false, false));
}
memberType.NoGroupPropertyTypes = propertyTypes;
memberType.PropertyTypes = propertyTypes;
return memberType;
}
private PropertyGroupCollection GetPropertyTypeGroupCollection(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary<string, PropertyType> standardProps)
{
// see PropertyGroupFactory, repeating code here...
var propertyGroups = new PropertyGroupCollection();
var propertyGroups = new PropertyGroupCollection();
foreach (var groupDto in dto.PropertyTypeGroups.Where(x => x.Id.HasValue))
{
var group = new PropertyGroup();
// if the group is defined on the current member type,
// assign its identifier, else it will be zero
//Only assign an Id if the PropertyGroup belongs to this ContentType
if (groupDto.ContentTypeNodeId == memberType.Id)
{
// note: no idea why Id is nullable here, but better check
if (groupDto.Id.HasValue == false)
throw new Exception("oops: groupDto.Id has no value.");
group.Id = groupDto.Id.Value;
if (groupDto.ParentGroupId.HasValue)
group.ParentId = groupDto.ParentGroupId.Value;
}
else
{
//If the PropertyGroup is inherited, we add a reference to the group as a Parent.
group.ParentId = groupDto.Id;
}
group.Name = groupDto.Text;
@@ -63,9 +63,7 @@ namespace Umbraco.Core.Persistence.Factories
//Check if property has an Id and set it, so that it can be updated if it already exists
if (property.HasIdentity)
{
dto.Id = property.Id;
}
if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer)
{
@@ -84,21 +82,11 @@ namespace Umbraco.Core.Persistence.Factories
}
}
}
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Decimal && property.Value != null)
{
decimal val;
if (decimal.TryParse(property.Value.ToString(), out val))
{
dto.Decimal = val;
}
}
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false)
{
DateTime date;
if (DateTime.TryParse(property.Value.ToString(), out date))
{
if(DateTime.TryParse(property.Value.ToString(), out date))
dto.Date = date;
}
}
else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext && property.Value != null)
{
@@ -8,21 +8,21 @@ namespace Umbraco.Core.Persistence.Factories
{
internal class PropertyGroupFactory
{
private readonly int _contentTypeId;
private readonly int _id;
private readonly DateTime _createDate;
private readonly DateTime _updateDate;
//a callback to create a property type which can be injected via a contructor
private readonly Func<string, DataTypeDatabaseType, string, PropertyType> _propertyTypeCtor;
public PropertyGroupFactory(int contentTypeId)
public PropertyGroupFactory(int id)
{
_contentTypeId = contentTypeId;
_id = id;
_propertyTypeCtor = (propertyEditorAlias, dbType, alias) => new PropertyType(propertyEditorAlias, dbType);
}
public PropertyGroupFactory(int contentTypeId, DateTime createDate, DateTime updateDate, Func<string, DataTypeDatabaseType, string, PropertyType> propertyTypeCtor)
public PropertyGroupFactory(int id, DateTime createDate, DateTime updateDate, Func<string, DataTypeDatabaseType, string, PropertyType> propertyTypeCtor)
{
_contentTypeId = contentTypeId;
_id = id;
_createDate = createDate;
_updateDate = updateDate;
_propertyTypeCtor = propertyTypeCtor;
@@ -30,24 +30,29 @@ namespace Umbraco.Core.Persistence.Factories
#region Implementation of IEntityFactory<IEnumerable<PropertyGroup>,IEnumerable<TabDto>>
public IEnumerable<PropertyGroup> BuildEntity(IEnumerable<PropertyTypeGroupDto> groupDtos)
public IEnumerable<PropertyGroup> BuildEntity(IEnumerable<PropertyTypeGroupDto> dto)
{
// groupDtos contains all the groups, those that are defined on the current
// content type, and those that are inherited from composition content types
var propertyGroups = new PropertyGroupCollection();
foreach (var groupDto in groupDtos)
foreach (var groupDto in dto)
{
var group = new PropertyGroup();
// if the group is defined on the current content type,
// assign its identifier, else it will be zero
if (groupDto.ContentTypeNodeId == _contentTypeId)
//Only assign an Id if the PropertyGroup belongs to this ContentType
if (groupDto.ContentTypeNodeId == _id)
{
group.Id = groupDto.Id;
if (groupDto.ParentGroupId.HasValue)
group.ParentId = groupDto.ParentGroupId.Value;
}
else
{
//If the PropertyGroup is inherited, we add a reference to the group as a Parent.
group.ParentId = groupDto.Id;
}
group.Name = groupDto.Text;
group.SortOrder = groupDto.SortOrder;
group.PropertyTypes = new PropertyTypeCollection();
group.Key = groupDto.UniqueId;
//Because we are likely to have a group with no PropertyTypes we need to ensure that these are excluded
var typeDtos = groupDto.PropertyTypeDtos.Where(x => x.Id > 0);
@@ -96,12 +101,14 @@ namespace Umbraco.Core.Persistence.Factories
{
var dto = new PropertyTypeGroupDto
{
ContentTypeNodeId = _contentTypeId,
ContentTypeNodeId = _id,
SortOrder = propertyGroup.SortOrder,
Text = propertyGroup.Name,
UniqueId = propertyGroup.Key
Text = propertyGroup.Name
};
if (propertyGroup.ParentId.HasValue)
dto.ParentGroupId = propertyGroup.ParentId.Value;
if (propertyGroup.HasIdentity)
dto.Id = propertyGroup.Id;
@@ -115,14 +122,14 @@ namespace Umbraco.Core.Persistence.Factories
var propertyTypeDto = new PropertyTypeDto
{
Alias = propertyType.Alias,
ContentTypeId = _contentTypeId,
ContentTypeId = _id,
DataTypeId = propertyType.DataTypeDefinitionId,
Description = propertyType.Description,
Mandatory = propertyType.Mandatory,
Name = propertyType.Name,
SortOrder = propertyType.SortOrder,
ValidationRegExp = propertyType.ValidationRegExp,
UniqueId = propertyType.Key
UniqueId = propertyType.Key == Guid.Empty ? Guid.NewGuid() : propertyType.Key
};
if (tabId != default(int))
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Persistence.Mappers
internal override void BuildMap()
{
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.Id, dto => dto.Id);
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.ParentId, dto => dto.ParentGroupId);
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.SortOrder, dto => dto.SortOrder);
CacheMap<PropertyGroup, PropertyTypeGroupDto>(src => src.Name, dto => dto.Text);
}
@@ -39,7 +39,6 @@ namespace Umbraco.Core.Persistence.Mappers
{
CacheMap<Template, TemplateDto>(src => src.Id, dto => dto.NodeId);
CacheMap<Template, NodeDto>(src => src.MasterTemplateId, dto => dto.ParentId);
CacheMap<Template, NodeDto>(src => src.Key, dto => dto.UniqueId);
CacheMap<Template, TemplateDto>(src => src.Alias, dto => dto.Alias);
CacheMap<Template, TemplateDto>(src => src.Content, dto => dto.Design);
}
@@ -117,7 +117,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -42, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-42", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -38, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-38", SortOrder = 2, UniqueId = new Guid("fd9f1447-6c61-4a7c-9595-5aa39147d318"), Text = "Folder Browser", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultContentListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-95", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
@@ -178,16 +179,16 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
private void CreateCmsPropertyTypeGroupData()
{
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Image) });
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 4, ContentTypeNodeId = 1033, Text = "File", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.File) });
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 5, ContentTypeNodeId = 1031, Text = "Contents", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Contents) });
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1 });
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 4, ContentTypeNodeId = 1033, Text = "File", SortOrder = 1 });
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 5, ContentTypeNodeId = 1031, Text = "Contents", SortOrder = 1 });
//membership property group
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 11, ContentTypeNodeId = 1044, Text = "Membership", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Membership) });
_database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 11, ContentTypeNodeId = 1044, Text = "Membership", SortOrder = 1 });
}
private void CreateCmsPropertyTypeData()
{
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = -90, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
@@ -195,7 +196,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 27, UniqueId = 27.ToGuid(), DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, ContentTypeId = 1031, PropertyTypeGroupId = 5, Alias = "contents", Name = "Contents:", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 27, UniqueId = 27.ToGuid(), DataTypeId = -38, ContentTypeId = 1031, PropertyTypeGroupId = 5, Alias = "contents", Name = "Contents:", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
//membership property types
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null });
_database.Insert("cmsPropertyType", "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null });
@@ -230,7 +231,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, PropertyEditorAlias = Constants.PropertyEditors.UploadFieldAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, PropertyEditorAlias = Constants.PropertyEditors.NoEditAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, PropertyEditorAlias = Constants.PropertyEditors.DateTimeAlias, DbType = "Date" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, PropertyEditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, PropertyEditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 10, DataTypeId = -38, PropertyEditorAlias = Constants.PropertyEditors.FolderBrowserAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, PropertyEditorAlias = Constants.PropertyEditors.DropDownListMultipleAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
@@ -251,6 +253,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = 1038, PropertyEditorAlias = Constants.PropertyEditors.MarkdownEditorAlias, DbType = "Ntext" });
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 20, DataTypeId = 1039, PropertyEditorAlias = Constants.PropertyEditors.UltimatePickerAlias, DbType = "Ntext" });
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 23, DataTypeId = 1042, PropertyEditorAlias = Constants.PropertyEditors.MacroContainerAlias, DbType = "Ntext" });
}
private void CreateCmsDataTypePreValuesData()
@@ -266,17 +269,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "Name" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -3, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "asc" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "[{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" });
//layouts for the list view
var cardLayout = "{\"name\": \"Grid\",\"path\": \"views/propertyeditors/listview/layouts/grid/grid.html\", \"icon\": \"icon-thumbnails-small\", \"isSystem\": 1, \"selected\": true}";
var listLayout = "{\"name\": \"List\",\"path\": \"views/propertyeditors/listview/layouts/list/list.html\",\"icon\": \"icon-list\", \"isSystem\": 1,\"selected\": true}";
//defaults for the media list
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -5, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "100" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -6, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "VersionDate" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" });
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"sortOrder\",\"isSystem\":1, \"header\": \"Sort order\"},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
}
private void CreateUmbracoRelationTypeData()
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{4, typeof (ContentVersionDto)},
{5, typeof (DocumentDto)},
{6, typeof (ContentTypeTemplateDto)},
{6, typeof (DocumentTypeDto)},
{7, typeof (DataTypeDto)},
{8, typeof (DataTypePreValueDto)},
{9, typeof (DictionaryDto)},
@@ -82,9 +82,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{42, typeof (AccessRuleDto)},
{43, typeof(CacheInstructionDto)},
{44, typeof (ExternalLoginDto)},
{45, typeof (MigrationDto)},
{46, typeof (UmbracoDeployChecksumDto)},
{47, typeof (UmbracoDeployDependencyDto)}
{45, typeof (MigrationDto)}
};
#endregion
@@ -119,12 +119,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
return new Version(7, 2, 5);
}
//if the error is for umbracoDeployChecksum it must be the previous version to 7.4 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoDeployChecksum"))))
{
return new Version(7, 3, 4);
}
return UmbracoVersion.Current;
}
@@ -289,7 +289,7 @@ namespace Umbraco.Core.Persistence.Migrations
//NOTE: We CANNOT do this as part of the transaction!!! This is because when upgrading to 7.3, we cannot
// create the migrations table and then add data to it in the same transaction without issuing things like GO
// commands and since we need to support all Dbs, we need to just do this after the fact.
var exists = _migrationEntryService.FindEntry(GlobalSettings.UmbracoMigrationName, _targetVersion);
var exists = _migrationEntryService.FindEntry(_productName, _targetVersion);
if (exists == null)
{
_migrationEntryService.CreateEntry(_productName, _targetVersion);
@@ -1,29 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZero
{
[Migration("7.4.0", 1, GlobalSettings.UmbracoMigrationName)]
public class AddDataDecimalColumn : MigrationBase
{
public AddDataDecimalColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
//Don't exeucte if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("cmsPropertyData") && x.ColumnName.InvariantEquals("dataDecimal")) == false)
Create.Column("dataDecimal").OnTable("cmsPropertyData").AsDecimal().Nullable();
}
public override void Down()
{
}
}
}
@@ -1,48 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZero
{
[Migration("7.4.0", 5, GlobalSettings.UmbracoMigrationName)]
public class AddUmbracoDeployTables : MigrationBase
{
public AddUmbracoDeployTables(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
//Don't exeucte if the table is already there
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains("umbracoDeployChecksum")) return;
Create.Table("umbracoDeployChecksum")
.WithColumn("id").AsInt32().Identity().PrimaryKey("PK_umbracoDeployChecksum")
.WithColumn("entityType").AsString(32).NotNullable()
.WithColumn("entityGuid").AsGuid().Nullable()
.WithColumn("entityPath").AsString(256).Nullable()
.WithColumn("localChecksum").AsString(32).NotNullable()
.WithColumn("compositeChecksum").AsString(32).Nullable();
Create.Table("umbracoDeployDependency")
.WithColumn("sourceId").AsInt32().NotNullable().ForeignKey("FK_umbracoDeployDependency_umbracoDeployChecksum_id1", "umbracoDeployChecksum", "id")
.WithColumn("targetId").AsInt32().NotNullable().ForeignKey("FK_umbracoDeployDependency_umbracoDeployChecksum_id2", "umbracoDeployChecksum", "id")
.WithColumn("mode").AsInt32().NotNullable();
Create.PrimaryKey("PK_umbracoDeployDependency").OnTable("umbracoDeployDependency").Columns(new[] {"sourceId", "targetId"});
Create.Index("IX_umbracoDeployChecksum").OnTable("umbracoDeployChecksum")
.OnColumn("entityType")
.Ascending()
.OnColumn("entityGuid")
.Ascending()
.OnColumn("entityPath")
.Unique();
}
public override void Down()
{ }
}
}
@@ -1,80 +0,0 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZero
{
[Migration("7.4.0", 2, GlobalSettings.UmbracoMigrationName)]
public class AddUniqueIdPropertyTypeGroupColumn : MigrationBase
{
public AddUniqueIdPropertyTypeGroupColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
// don't execute if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("cmsPropertyTypeGroup") && x.ColumnName.InvariantEquals("uniqueID")) == false)
{
Create.Column("uniqueID").OnTable("cmsPropertyTypeGroup").AsGuid().NotNullable().WithDefault(SystemMethods.NewGuid);
// unique constraint on name + version
Create.Index("IX_cmsPropertyTypeGroupUniqueID").OnTable("cmsPropertyTypeGroup")
.OnColumn("uniqueID").Ascending()
.WithOptions()
.NonClustered()
.WithOptions()
.Unique();
// fill in the data in a way that is consistent over all environments
// (ie cannot use random guids, http://issues.umbraco.org/issue/U4-6942)
foreach (var data in Context.Database.Query<dynamic>(@"
SELECT cmsPropertyTypeGroup.id grId, cmsPropertyTypeGroup.text grName, cmsContentType.alias ctAlias, umbracoNode.nodeObjectType nObjType
FROM cmsPropertyTypeGroup
INNER JOIN cmsContentType
ON cmsPropertyTypeGroup.contentTypeNodeId = cmsContentType.nodeId
INNER JOIN umbracoNode
ON cmsContentType.nodeId = umbracoNode.id"))
{
Guid guid;
// see BaseDataCreation... built-in groups have their own guids
if (data.grId == 3)
{
guid = new Guid(Constants.PropertyTypeGroups.Image);
}
else if (data.grId == 4)
{
guid = new Guid(Constants.PropertyTypeGroups.File);
}
else if (data.grId == 5)
{
guid = new Guid(Constants.PropertyTypeGroups.Contents);
}
else if (data.grId == 11)
{
guid = new Guid(Constants.PropertyTypeGroups.Membership);
}
else
{
// create a consistent guid from
// group name + content type alias + object type
string guidSource = data.grName + data.ctAlias + data.nObjType;
guid = guidSource.ToGuid();
}
// set the Unique Id to the one we've generated
Update.Table("cmsPropertyTypeGroup").Set(new { uniqueID = guid }).Where(new { id = data.grId });
}
}
}
public override void Down()
{ }
}
}
@@ -1,55 +0,0 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZero
{
/// <summary>
/// Courier on v. 7.4+ will handle ContentTypes using GUIDs instead of
/// alias, so we need to ensure that these are initially consistent on
/// all environments (based on the alias).
/// </summary>
[Migration("7.4.0", 3, GlobalSettings.UmbracoMigrationName)]
public class EnsureContentTypeUniqueIdsAreConsistent : MigrationBase
{
public EnsureContentTypeUniqueIdsAreConsistent(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
var objectTypes = new[]
{
Constants.ObjectTypes.DocumentTypeGuid,
Constants.ObjectTypes.MediaTypeGuid,
Constants.ObjectTypes.MemberTypeGuid,
};
var sql = new Sql()
.Select("umbracoNode.id,cmsContentType.alias,umbracoNode.nodeObjectType")
.From<NodeDto>(SqlSyntax)
.InnerJoin<ContentTypeDto>(SqlSyntax)
.On<NodeDto, ContentTypeDto>(SqlSyntax, dto => dto.NodeId, dto => dto.NodeId)
.WhereIn<NodeDto>(x => x.NodeObjectType, objectTypes);
var rows = Context.Database.Fetch<dynamic>(sql);
foreach (var row in rows)
{
// create a consistent guid from
// alias + object type
var guidSource = ((string) row.alias) + ((Guid) row.nodeObjectType);
var guid = guidSource.ToGuid();
// set the Unique Id to the one we've generated
Update.Table("umbracoNode").Set(new { uniqueID = guid }).Where(new { id = row.id });
}
}
public override void Down()
{ }
}
}
@@ -1,34 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZero
{
[Migration("7.4.0", 4, GlobalSettings.UmbracoMigrationName)]
public class FixListViewMediaSortOrder : MigrationBase
{
public FixListViewMediaSortOrder(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
var mediaListviewIncludeProperties = Context.Database.Fetch<DataTypePreValueDto>(new Sql().Select("*").From<DataTypePreValueDto>(SqlSyntax).Where<DataTypePreValueDto>(x => x.Id == -9)).FirstOrDefault();
if (mediaListviewIncludeProperties != null)
{
if (mediaListviewIncludeProperties.Value.Contains("\"alias\":\"sort\""))
{
mediaListviewIncludeProperties.Value = mediaListviewIncludeProperties.Value.Replace("\"alias\":\"sort\"", "\"alias\":\"sortOrder\"");
Context.Database.InsertOrUpdate(mediaListviewIncludeProperties);
}
}
}
public override void Down()
{
}
}
}
@@ -1,30 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZero
{
[Migration("7.4.0", 4, GlobalSettings.UmbracoMigrationName)]
public class RemoveParentIdPropertyTypeGroupColumn : MigrationBase
{
public RemoveParentIdPropertyTypeGroupColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
// don't execute if the column is not there anymore
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("cmsPropertyTypeGroup") && x.ColumnName.InvariantEquals("parentGroupId")) == false)
return;
Delete.ForeignKey("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup_id").OnTable("cmsPropertyTypeGroup");
Delete.Column("parentGroupId").FromTable("cmsPropertyTypeGroup");
}
public override void Down()
{ }
}
}
@@ -5,13 +5,15 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
{
{
[Migration("7.3.0", 13, GlobalSettings.UmbracoMigrationName)]
public class AddUniqueIdPropertyTypeColumn : MigrationBase
{
public AddUniqueIdPropertyTypeColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
{
}
public override void Up()
{
@@ -22,7 +24,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
{
Create.Column("uniqueID").OnTable("cmsPropertyType").AsGuid().NotNullable().WithDefault(SystemMethods.NewGuid);
// unique constraint on name + version
//unique constraint on name + version
Create.Index("IX_cmsPropertyTypeUniqueID").OnTable("cmsPropertyType")
.OnColumn("uniqueID").Ascending()
.WithOptions()
@@ -30,8 +32,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
.WithOptions()
.Unique();
// fill in the data in a way that is consistent over all environments
// (ie cannot use random guids, http://issues.umbraco.org/issue/U4-6942)
//now we need to fill in the data so that it is consistent, we can't have it generating random GUIDs for
// the already existing data, see: http://issues.umbraco.org/issue/U4-6942
foreach (var data in Context.Database.Query<dynamic>(@"
SELECT cmsPropertyType.id ptId, cmsPropertyType.Alias ptAlias, cmsContentType.alias ctAlias, umbracoNode.nodeObjectType nObjType
@@ -41,18 +43,22 @@ ON cmsPropertyType.contentTypeId = cmsContentType.nodeId
INNER JOIN umbracoNode
ON cmsContentType.nodeId = umbracoNode.id"))
{
// create a consistent guid from
// property alias + content type alias + object type
string guidSource = data.ptAlias + data.ctAlias + data.nObjType;
var guid = guidSource.ToGuid();
//create a guid from the concatenation of the:
// property type alias + the doc type alias + the content type node object type
// - the latter is required because there can be a content type and media type with the same alias!!
string concatAlias = data.ptAlias + data.ctAlias + data.nObjType;
var ptGuid = concatAlias.ToGuid();
// set the Unique Id to the one we've generated
Update.Table("cmsPropertyType").Set(new { uniqueID = guid }).Where(new { id = data.ptId });
//set the Unique Id to the one we've generated
Update.Table("cmsPropertyType").Set(new {uniqueID = ptGuid}).Where(new {id = data.ptId });
}
}
}
public override void Down()
{ }
{
}
}
}
@@ -28,55 +28,60 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
{
if (database != null)
{
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
//NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns
// won't exist yet
//NOTE: We're using dynamic to avoid having this migration fail due to the UniqueId column added in 7.3 (this column is not added
// in the table yet and will make the mapping of done by Fetch fail when the actual type is used here).
var propertyTypes = database.Fetch<dynamic>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
var propertyGroups = database.Fetch<PropertyTypeGroupDto>("WHERE id > 0");
foreach (var propertyType in propertyTypes)
{
// get the PropertyTypeGroup of the current PropertyType, skip if not found
var propertyTypeGroup = propertyGroups.FirstOrDefault(x => x.Id == propertyType.propertyTypeGroupId);
if (propertyTypeGroup == null) continue;
// if the PropretyTypeGroup belongs to the same content type as the PropertyType, then fine
if (propertyTypeGroup.ContentTypeNodeId == propertyType.contentTypeId) continue;
// else we want to assign the PropertyType to a proper PropertyTypeGroup
// ie one that does belong to the same content - look for it
var okPropertyTypeGroup = propertyGroups.FirstOrDefault(x =>
x.Text == propertyTypeGroup.Text && // same name
x.ContentTypeNodeId == propertyType.contentTypeId); // but for proper content type
if (okPropertyTypeGroup == null)
//Get the PropertyTypeGroup that the current PropertyType references
var parentPropertyTypeGroup = propertyGroups.FirstOrDefault(x => x.Id == propertyType.propertyTypeGroupId);
if (parentPropertyTypeGroup != null)
{
// does not exist, create a new PropertyTypeGroup,
var propertyGroup = new PropertyTypeGroupDto
//If the ContentType is the same on the PropertyType and the PropertyTypeGroup the group is valid and we skip to the next
if (parentPropertyTypeGroup.ContentTypeNodeId == propertyType.contentTypeId) continue;
//Check if the 'new' PropertyTypeGroup has already been created
var existingPropertyTypeGroup =
propertyGroups.FirstOrDefault(
x =>
x.ParentGroupId == parentPropertyTypeGroup.Id && x.Text == parentPropertyTypeGroup.Text &&
x.ContentTypeNodeId == propertyType.contentTypeId);
//This should ensure that we don't create duplicate groups for a single ContentType
if (existingPropertyTypeGroup == null)
{
ContentTypeNodeId = propertyType.contentTypeId,
Text = propertyTypeGroup.Text,
SortOrder = propertyTypeGroup.SortOrder
};
//Create a new PropertyTypeGroup that references the parent group that the PropertyType was referencing pre-6.0.1
var propertyGroup = new PropertyTypeGroupDto
{
ContentTypeNodeId = propertyType.contentTypeId,
ParentGroupId = parentPropertyTypeGroup.Id,
Text = parentPropertyTypeGroup.Text,
SortOrder = parentPropertyTypeGroup.SortOrder
};
// save + add to list of groups
int id = Convert.ToInt16(database.Insert(propertyGroup));
propertyGroup.Id = id;
propertyGroups.Add(propertyGroup);
// update the PropertyType to use the new PropertyTypeGroup
propertyType.propertyTypeGroupId = id;
//Save the PropertyTypeGroup in the database and update the list of groups with this new group
int id = Convert.ToInt16(database.Insert(propertyGroup));
propertyGroup.Id = id;
propertyGroups.Add(propertyGroup);
//Update the reference to the new PropertyTypeGroup on the current PropertyType
propertyType.propertyTypeGroupId = id;
database.Update("cmsPropertyType", "id", propertyType);
}
else
{
//Update the reference to the existing PropertyTypeGroup on the current PropertyType
propertyType.propertyTypeGroupId = existingPropertyTypeGroup.Id;
database.Update("cmsPropertyType", "id", propertyType);
}
}
else
{
// exists, update PropertyType to use the PropertyTypeGroup
propertyType.propertyTypeGroupId = okPropertyTypeGroup.Id;
}
database.Update("cmsPropertyType", "id", propertyType);
}
}
return string.Empty;
}
}
+1 -1
View File
@@ -834,7 +834,7 @@ namespace Umbraco.Core.Persistence
var pd = PocoData.ForType(typeof(T));
try
{
r = cmd.ExecuteReader();
r = cmd.ExecuteReaderWithRetry();
OnExecutedCommand(cmd);
}
catch (Exception x)
@@ -18,8 +18,11 @@ namespace Umbraco.Core.Persistence.Relators
// Is this the same DictionaryItem as the current one we're processing
if (Current != null && Current.Id == a.Id)
{
// Yes, just add this User2AppDto to the current item's collection
Current.User2AppDtos.Add(p);
if (p.AppAlias.IsNullOrWhiteSpace() == false)
{
// Yes, just add this User2AppDto to the current item's collection
Current.User2AppDtos.Add(p);
}
// Return null to indicate we're not done with this User yet
return null;
@@ -35,7 +38,7 @@ namespace Umbraco.Core.Persistence.Relators
Current = a;
Current.User2AppDtos = new List<User2AppDto>();
//this can be null since we are doing a left join
if (p.AppAlias != null)
if (p.AppAlias.IsNullOrWhiteSpace() == false)
{
Current.User2AppDtos.Add(p);
}
@@ -155,8 +155,8 @@ namespace Umbraco.Core.Persistence.Repositories
"DELETE FROM cmsContentVersion WHERE ContentId = @Id",
"DELETE FROM cmsContentXml WHERE nodeId = @Id",
"DELETE FROM cmsContent WHERE nodeId = @Id",
"DELETE FROM umbracoNode WHERE id = @Id",
"DELETE FROM umbracoAccess WHERE nodeId = @Id"
"DELETE FROM umbracoAccess WHERE nodeId = @Id",
"DELETE FROM umbracoNode WHERE id = @Id"
};
return list;
}
File diff suppressed because it is too large Load Diff
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
@@ -13,7 +12,6 @@ using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Relators;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -28,42 +26,54 @@ namespace Umbraco.Core.Persistence.Repositories
: base(work, cache, logger, sqlSyntax)
{
_templateRepository = templateRepository;
}
}
private FullDataSetRepositoryCachePolicyFactory<IContentType, int> _cachePolicyFactory;
protected override IRepositoryCachePolicyFactory<IContentType, int> CachePolicyFactory
{
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IContentType, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(),
//allow this cache to expire
expires:true));
}
}
protected override IContentType PerformGet(int id)
{
var contentTypes = ContentTypeQueryMapper.GetContentTypes(
new[] {id}, Database, SqlSyntax, this, _templateRepository);
var contentType = contentTypes.SingleOrDefault();
return contentType;
//use the underlying GetAll which will force cache all content types
return GetAll().FirstOrDefault(x => x.Id == id);
}
protected override IEnumerable<IContentType> PerformGetAll(params int[] ids)
{
if (ids.Any())
{
return ContentTypeQueryMapper.GetContentTypes(ids, Database, SqlSyntax, this, _templateRepository);
}
else
{
var sql = new Sql().Select("id").From<NodeDto>(SqlSyntax).Where<NodeDto>(dto => dto.NodeObjectType == NodeObjectTypeId);
var allIds = Database.Fetch<int>(sql).ToArray();
return ContentTypeQueryMapper.GetContentTypes(allIds, Database, SqlSyntax, this, _templateRepository);
//NOTE: This logic should never be executed according to our cache policy
return ContentTypeQueryMapper.GetContentTypes(Database, SqlSyntax, this, _templateRepository)
.Where(x => ids.Contains(x.Id));
}
return ContentTypeQueryMapper.GetContentTypes(Database, SqlSyntax, this, _templateRepository);
}
protected override IEnumerable<IContentType> PerformGetByQuery(IQuery<IContentType> query)
{
var sqlClause = GetBaseQuery(false);
var translator = new SqlTranslator<IContentType>(sqlClause, query);
var sql = translator.Translate()
.OrderBy<NodeDto>(x => x.Text, SqlSyntax);
var sql = translator.Translate();
var dtos = Database.Fetch<ContentTypeTemplateDto, ContentTypeDto, NodeDto>(sql);
return dtos.Any()
? GetAll(dtos.DistinctBy(x => x.ContentTypeDto.NodeId).Select(x => x.ContentTypeDto.NodeId).ToArray())
: Enumerable.Empty<IContentType>();
var dtos = Database.Fetch<DocumentTypeDto, ContentTypeDto, NodeDto>(sql);
return
//This returns a lookup from the GetAll cached looup
(dtos.Any()
? GetAll(dtos.DistinctBy(x => x.ContentTypeDto.NodeId).Select(x => x.ContentTypeDto.NodeId).ToArray())
: Enumerable.Empty<IContentType>())
//order the result by name
.OrderBy(x => x.Name);
}
/// <summary>
@@ -87,17 +97,19 @@ namespace Umbraco.Core.Persistence.Repositories
{
return Database.Fetch<string>("SELECT DISTINCT Alias FROM cmsPropertyType ORDER BY Alias");
}
#region Overrides of PetaPocoRepositoryBase<int,IContentType>
protected override Sql GetBaseQuery(bool isCount)
{
var sql = new Sql();
sql.Select(isCount ? "COUNT(*)" : "*")
.From<ContentTypeDto>(SqlSyntax)
.InnerJoin<NodeDto>(SqlSyntax)
.On<ContentTypeDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
.LeftJoin<ContentTypeTemplateDto>(SqlSyntax)
.On<ContentTypeTemplateDto, ContentTypeDto>(SqlSyntax, left => left.ContentTypeNodeId, right => right.NodeId)
.From<ContentTypeDto>()
.InnerJoin<NodeDto>()
.On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.LeftJoin<DocumentTypeDto>()
.On<DocumentTypeDto, ContentTypeDto>(left => left.ContentTypeNodeId, right => right.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
return sql;
@@ -132,7 +144,11 @@ namespace Umbraco.Core.Persistence.Repositories
{
get { return new Guid(Constants.ObjectTypes.DocumentType); }
}
#endregion
#region Unit of Work Implementation
/// <summary>
/// Deletes a content type
/// </summary>
@@ -171,39 +187,26 @@ namespace Umbraco.Core.Persistence.Repositories
((ContentType)entity).AddingEntity();
PersistNewBaseContentType(entity);
PersistTemplates(entity, false);
var factory = new ContentTypeFactory(NodeObjectTypeId);
var dto = factory.BuildDto(entity);
PersistNewBaseContentType(dto.ContentTypeDto, entity);
//Inserts data into the cmsDocumentType table if a template exists
if (dto.TemplateNodeId > 0)
{
dto.ContentTypeNodeId = entity.Id;
Database.Insert(dto);
}
//Insert allowed Templates not including the default one, as that has already been inserted
foreach (var template in entity.AllowedTemplates.Where(x => x != null && x.Id != dto.TemplateNodeId))
{
Database.Insert(new DocumentTypeDto { ContentTypeNodeId = entity.Id, TemplateNodeId = template.Id, IsDefault = false });
}
entity.ResetDirtyProperties();
}
protected void PersistTemplates(IContentType entity, bool clearAll)
{
// remove and insert, if required
Database.Delete<ContentTypeTemplateDto>("WHERE contentTypeNodeId = @Id", new { Id = entity.Id });
// we could do it all in foreach if we assume that the default template is an allowed template??
var defaultTemplateId = ((ContentType) entity).DefaultTemplateId;
if (defaultTemplateId > 0)
{
Database.Insert(new ContentTypeTemplateDto
{
ContentTypeNodeId = entity.Id,
TemplateNodeId = defaultTemplateId,
IsDefault = true
});
}
foreach (var template in entity.AllowedTemplates.Where(x => x != null && x.Id != defaultTemplateId))
{
Database.Insert(new ContentTypeTemplateDto
{
ContentTypeNodeId = entity.Id,
TemplateNodeId = template.Id,
IsDefault = false
});
}
}
protected override void PersistUpdatedItem(IContentType entity)
{
ValidateAlias(entity);
@@ -224,33 +227,59 @@ namespace Umbraco.Core.Persistence.Repositories
entity.SortOrder = maxSortOrder + 1;
}
PersistUpdatedBaseContentType(entity);
PersistTemplates(entity, true);
var factory = new ContentTypeFactory(NodeObjectTypeId);
var dto = factory.BuildDto(entity);
PersistUpdatedBaseContentType(dto.ContentTypeDto, entity);
//Look up DocumentType entries for updating - this could possibly be a "remove all, insert all"-approach
Database.Delete<DocumentTypeDto>("WHERE contentTypeNodeId = @Id", new { Id = entity.Id });
//Insert the updated DocumentTypeDto if a template exists
if (dto.TemplateNodeId > 0)
{
Database.Insert(dto);
}
//Insert allowed Templates not including the default one, as that has already been inserted
foreach (var template in entity.AllowedTemplates.Where(x => x != null && x.Id != dto.TemplateNodeId))
{
Database.Insert(new DocumentTypeDto { ContentTypeNodeId = entity.Id, TemplateNodeId = template.Id, IsDefault = false });
}
entity.ResetDirtyProperties();
}
#endregion
protected override IContentType PerformGet(Guid id)
{
var contentTypes = ContentTypeQueryMapper.GetContentTypes(
new[] { id }, Database, SqlSyntax, this, _templateRepository);
//use the underlying GetAll which will force cache all content types
return GetAll().FirstOrDefault(x => x.Key == id);
}
var contentType = contentTypes.SingleOrDefault();
return contentType;
protected override IContentType PerformGet(string alias)
{
//use the underlying GetAll which will force cache all content types
return GetAll().FirstOrDefault(x => x.Alias.InvariantEquals(alias));
}
protected override IEnumerable<IContentType> PerformGetAll(params Guid[] ids)
{
//use the underlying GetAll which will force cache all content types
if (ids.Any())
{
return ContentTypeQueryMapper.GetContentTypes(ids, Database, SqlSyntax, this, _templateRepository);
return GetAll().Where(x => ids.Contains(x.Key));
}
else
{
var sql = new Sql().Select("id").From<NodeDto>(SqlSyntax).Where<NodeDto>(dto => dto.NodeObjectType == NodeObjectTypeId);
var allIds = Database.Fetch<int>(sql).ToArray();
return ContentTypeQueryMapper.GetContentTypes(allIds, Database, SqlSyntax, this, _templateRepository);
return GetAll();
}
}
protected override bool PerformExists(Guid id)
{
return GetAll().FirstOrDefault(x => x.Key == id) != null;
}
}
}
@@ -6,8 +6,6 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
@@ -116,9 +114,9 @@ namespace Umbraco.Core.Persistence.Repositories
{
var sql = new Sql();
sql.Select(isCount ? "COUNT(*)" : "*")
.From<DataTypeDto>(SqlSyntax)
.InnerJoin<NodeDto>(SqlSyntax)
.On<DataTypeDto, NodeDto>(SqlSyntax, left => left.DataTypeId, right => right.NodeId)
.From<DataTypeDto>()
.InnerJoin<NodeDto>()
.On<DataTypeDto, NodeDto>(left => left.DataTypeId, right => right.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
return sql;
}
@@ -146,10 +144,6 @@ namespace Umbraco.Core.Persistence.Repositories
{
((DataTypeDefinition)entity).AddingEntity();
//ensure a datatype has a unique name before creating it
entity.Name = EnsureUniqueNodeName(entity.Name);
//TODO: should the below be removed?
//Cannot add a duplicate data type
var exists = Database.ExecuteScalar<int>(@"SELECT COUNT(*) FROM cmsDataType
INNER JOIN umbracoNode ON cmsDataType.nodeId = umbracoNode.id
@@ -195,8 +189,6 @@ WHERE umbracoNode." + SqlSyntax.GetQuotedColumnName("text") + "= @name", new { n
protected override void PersistUpdatedItem(IDataTypeDefinition entity)
{
entity.Name = EnsureUniqueNodeName(entity.Name, entity.Id);
//Cannot change to a duplicate alias
var exists = Database.ExecuteScalar<int>(@"SELECT COUNT(*) FROM cmsDataType
INNER JOIN umbracoNode ON cmsDataType.nodeId = umbracoNode.id
@@ -329,47 +321,6 @@ AND umbracoNode.id <> @id",
AddOrUpdatePreValues(dtd, values);
}
public IEnumerable<MoveEventInfo<IDataTypeDefinition>> Move(IDataTypeDefinition toMove, EntityContainer container)
{
var parentId = -1;
if (container != null)
{
// Check on paths
if ((string.Format(",{0},", container.Path)).IndexOf(string.Format(",{0},", toMove.Id), StringComparison.Ordinal) > -1)
{
throw new DataOperationException<MoveOperationStatusType>(MoveOperationStatusType.FailedNotAllowedByPath);
}
parentId = container.Id;
}
//used to track all the moved entities to be given to the event
var moveInfo = new List<MoveEventInfo<IDataTypeDefinition>>
{
new MoveEventInfo<IDataTypeDefinition>(toMove, toMove.Path, parentId)
};
//do the move to a new parent
toMove.ParentId = parentId;
//schedule it for updating in the transaction
AddOrUpdate(toMove);
//update all descendants
var descendants = this.GetByQuery(
new Query<IDataTypeDefinition>().Where(type => type.Path.StartsWith(toMove.Path + ",")));
foreach (var descendant in descendants)
{
moveInfo.Add(new MoveEventInfo<IDataTypeDefinition>(descendant, descendant.Path, descendant.ParentId));
//all we're doing here is setting the parent Id to be dirty so that it resets the path/level/etc...
descendant.ParentId = descendant.ParentId + 1;
descendant.ParentId = descendant.ParentId - 1;
//schedule it for updating in the transaction
AddOrUpdate(descendant);
}
return moveInfo;
}
public void AddOrUpdatePreValues(IDataTypeDefinition dataType, IDictionary<string, PreValue> values)
{
var currentVals = new DataTypePreValueDto[] { };
@@ -377,9 +328,9 @@ AND umbracoNode.id <> @id",
{
//first just get all pre-values for this data type so we can compare them to see if we need to insert or update or replace
var sql = new Sql().Select("*")
.From<DataTypePreValueDto>(SqlSyntax)
.From<DataTypePreValueDto>()
.Where<DataTypePreValueDto>(dto => dto.DataTypeNodeId == dataType.Id)
.OrderBy<DataTypePreValueDto>(dto => dto.SortOrder, SqlSyntax);
.OrderBy<DataTypePreValueDto>(dto => dto.SortOrder);
currentVals = Database.Fetch<DataTypePreValueDto>(sql).ToArray();
}
@@ -464,37 +415,6 @@ AND umbracoNode.id <> @id",
return collection;
}
private string EnsureUniqueNodeName(string nodeName, int id = 0)
{
var sql = new Sql();
sql.Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId && x.Text.StartsWith(nodeName));
int uniqueNumber = 1;
var currentName = nodeName;
var dtos = Database.Fetch<NodeDto>(sql);
if (dtos.Any())
{
var results = dtos.OrderBy(x => x.Text, new SimilarNodeNameComparer());
foreach (var dto in results)
{
if (id != 0 && id == dto.NodeId) continue;
if (dto.Text.ToLowerInvariant().Equals(currentName.ToLowerInvariant()))
{
currentName = nodeName + string.Format(" ({0})", uniqueNumber);
uniqueNumber++;
}
}
}
return currentName;
}
/// <summary>
/// Private class to handle pre-value crud based on units of work with transactions
/// </summary>
@@ -605,8 +525,6 @@ AND umbracoNode.id <> @id",
};
Database.Update(dto);
}
}
internal static class PreValueConverter
@@ -29,7 +29,8 @@ namespace Umbraco.Core.Persistence.Repositories
get
{
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IDomain, int>(RuntimeCache));
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IDomain, int>(
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
}
}
@@ -1,255 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
/// An internal repository for managing entity containers such as doc type, media type, data type containers.
/// </summary>
internal class EntityContainerRepository : PetaPocoRepositoryBase<int, EntityContainer>
{
public EntityContainerRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax)
: base(work, cache, logger, sqlSyntax)
{ }
/// <summary>
/// Do not cache anything
/// </summary>
protected override IRuntimeCacheProvider RuntimeCache
{
get { return new NullCacheProvider(); }
}
protected override EntityContainer PerformGet(int id)
{
var sql = GetBaseQuery(false).Where(GetBaseWhereClause(), new { id });
var nodeDto = Database.Fetch<NodeDto>(sql).FirstOrDefault();
return nodeDto == null ? null : CreateEntity(nodeDto);
}
// temp - so we don't have to implement GetByQuery
public EntityContainer Get(Guid id)
{
var sql = GetBaseQuery(false).Where("UniqueId=@uniqueId", new { uniqueId = id });
var nodeDto = Database.Fetch<NodeDto>(sql).FirstOrDefault();
return nodeDto == null ? null : CreateEntity(nodeDto);
}
public IEnumerable<EntityContainer> Get(string name, int level, Guid umbracoObjectTypeId)
{
var sql = GetBaseQuery(false).Where("text=@name AND level=@level AND nodeObjectType=@umbracoObjectTypeId", new { name, level, umbracoObjectTypeId });
return Database.Fetch<NodeDto>(sql).Select(CreateEntity);
}
protected override IEnumerable<EntityContainer> PerformGetAll(params int[] ids)
{
throw new NotImplementedException();
}
protected override IEnumerable<EntityContainer> PerformGetByQuery(IQuery<EntityContainer> query)
{
throw new NotImplementedException();
}
private static EntityContainer CreateEntity(NodeDto nodeDto)
{
if (nodeDto.NodeObjectType.HasValue == false)
throw new InvalidOperationException("Node with id " + nodeDto.NodeId + " has no object type.");
// throws if node is not a container
var containedObjectType = EntityContainer.GetContainedObjectType(nodeDto.NodeObjectType.Value);
var entity = new EntityContainer(nodeDto.NodeId, nodeDto.UniqueId,
nodeDto.ParentId, nodeDto.Path, nodeDto.Level, nodeDto.SortOrder,
containedObjectType,
nodeDto.Text, nodeDto.UserId ?? 0);
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
entity.ResetDirtyProperties(false);
return entity;
}
protected override Sql GetBaseQuery(bool isCount)
{
var sql = new Sql();
if (isCount)
{
sql.Select("COUNT(*)").From<NodeDto>(SqlSyntax);
}
else
{
sql.Select("*").From<NodeDto>(SqlSyntax);
}
return sql;
}
protected override string GetBaseWhereClause()
{
return "umbracoNode.id = @id"; //" and nodeObjectType = @NodeObjectType";
}
protected override IEnumerable<string> GetDeleteClauses()
{
throw new NotImplementedException();
}
protected override Guid NodeObjectTypeId
{
get { throw new NotImplementedException(); }
}
protected override void PersistDeletedItem(EntityContainer entity)
{
var nodeDto = Database.FirstOrDefault<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(dto => dto.NodeId == entity.Id && dto.NodeObjectType == entity.ContainerObjectType));
if (nodeDto == null) return;
// move children to the parent so they are not orphans
var childDtos = Database.Fetch<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where("parentID=@parentID AND (nodeObjectType=@containedObjectType OR nodeObjectType=@containerObjectType)",
new
{
parentID = entity.Id,
containedObjectType = entity.ContainedObjectType,
containerObjectType = entity.ContainerObjectType
}));
foreach (var childDto in childDtos)
{
childDto.ParentId = nodeDto.ParentId;
Database.Update(childDto);
}
// delete
Database.Delete(nodeDto);
}
protected override void PersistNewItem(EntityContainer entity)
{
entity.Name = entity.Name.Trim();
Mandate.ParameterNotNullOrEmpty(entity.Name, "entity.Name");
// guard against duplicates
var nodeDto = Database.FirstOrDefault<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(dto => dto.ParentId == entity.ParentId && dto.Text == entity.Name && dto.NodeObjectType == entity.ContainerObjectType));
if (nodeDto != null)
throw new InvalidOperationException("A container with the same name already exists.");
// create
var level = 0;
var path = "-1";
if (entity.ParentId > -1)
{
var parentDto = Database.FirstOrDefault<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType));
if (parentDto == null)
throw new NullReferenceException("Could not find parent container with id " + entity.ParentId);
level = parentDto.Level;
path = parentDto.Path;
}
// note: sortOrder is NOT managed and always zero for containers
nodeDto = new NodeDto
{
CreateDate = DateTime.Now,
Level = Convert.ToInt16(level + 1),
NodeObjectType = entity.ContainerObjectType,
ParentId = entity.ParentId,
Path = path,
SortOrder = 0,
Text = entity.Name,
UserId = entity.CreatorId,
UniqueId = entity.Key
};
// insert, get the id, update the path with the id
var id = Convert.ToInt32(Database.Insert(nodeDto));
nodeDto.Path = nodeDto.Path + "," + nodeDto.NodeId;
Database.Save(nodeDto);
// refresh the entity
entity.Id = id;
entity.Path = nodeDto.Path;
entity.Level = nodeDto.Level;
entity.SortOrder = 0;
entity.CreateDate = nodeDto.CreateDate;
entity.ResetDirtyProperties();
}
// beware! does NOT manage descendants in case of a new parent
//
protected override void PersistUpdatedItem(EntityContainer entity)
{
entity.Name = entity.Name.Trim();
Mandate.ParameterNotNullOrEmpty(entity.Name, "entity.Name");
// find container to update
var nodeDto = Database.FirstOrDefault<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(dto => dto.NodeId == entity.Id && dto.NodeObjectType == entity.ContainerObjectType));
if (nodeDto == null)
throw new InvalidOperationException("Could not find container with id " + entity.Id);
// guard against duplicates
var dupNodeDto = Database.FirstOrDefault<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(dto => dto.ParentId == entity.ParentId && dto.Text == entity.Name && dto.NodeObjectType == entity.ContainerObjectType));
if (dupNodeDto != null && dupNodeDto.NodeId != nodeDto.NodeId)
throw new InvalidOperationException("A container with the same name already exists.");
// update
nodeDto.Text = entity.Name;
if (nodeDto.ParentId != entity.ParentId)
{
nodeDto.Level = 0;
nodeDto.Path = "-1";
if (entity.ParentId > -1)
{
var parent = Database.FirstOrDefault<NodeDto>(new Sql().Select("*")
.From<NodeDto>(SqlSyntax)
.Where<NodeDto>(dto => dto.NodeId == entity.ParentId && dto.NodeObjectType == entity.ContainerObjectType));
if (parent == null)
throw new NullReferenceException("Could not find parent container with id " + entity.ParentId);
nodeDto.Level = Convert.ToInt16(parent.Level + 1);
nodeDto.Path = parent.Path + "," + nodeDto.NodeId;
}
nodeDto.ParentId = entity.ParentId;
}
// note: sortOrder is NOT managed and always zero for containers
// update
Database.Update(nodeDto);
// refresh the entity
entity.Path = nodeDto.Path;
entity.Level = nodeDto.Level;
entity.SortOrder = 0;
entity.ResetDirtyProperties();
}
}
}

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