Compare commits
456 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e12f24af94 | |||
| cbad216387 | |||
| 00880fcbfa | |||
| 080ed612e8 | |||
| 5661a34e00 | |||
| 85012ee82a | |||
| 53a9cdb7a0 | |||
| 6b6ca615ba | |||
| 2eef061c42 | |||
| 70f65583d7 | |||
| 0d37a1f6e8 | |||
| 389724cba5 | |||
| 0382902984 | |||
| e0a0216b2d | |||
| b02f7e0d3a | |||
| 9d96a4411f | |||
| 8e9a9dc996 | |||
| b1603a21a2 | |||
| 59cb1ad31e | |||
| 215ebb78ca | |||
| c1796dd5ac | |||
| 28550e3bb7 | |||
| bc59ff2e8c | |||
| 614327a273 | |||
| ed292d34db | |||
| 5ac3eb7fef | |||
| 94732cff00 | |||
| 7947682cf0 | |||
| 6506768f10 | |||
| 9e0d10d0a3 | |||
| 392b18f4dd | |||
| c3ecc9e942 | |||
| c47f9ae26d | |||
| 22b506e2fb | |||
| 516723d31d | |||
| 7c30f26505 | |||
| 6b84a6adec | |||
| 6e2493854a | |||
| 1e13746cd0 | |||
| 8c7adf80b2 | |||
| c38c2ede11 | |||
| a6cd2b9e18 | |||
| 5fa128697b | |||
| 62c3bf6afe | |||
| aec862a9de | |||
| cfd21bc924 | |||
| d264792e18 | |||
| af732955fb | |||
| a846ba64eb | |||
| d3e925add9 | |||
| 683f0c5725 | |||
| 6827def8ba | |||
| dbbe3fe5fb | |||
| d2a20b10aa | |||
| 27e6b8c80c | |||
| 956a92f5b4 | |||
| 36c7fd53cb | |||
| 3df2d03fc8 | |||
| 16c360de88 | |||
| c661fc6537 | |||
| c2c5098045 | |||
| 16d98488e4 | |||
| 5a862f5c64 | |||
| caf41b74b8 | |||
| e858f4ff1e | |||
| 851961ef2b | |||
| c139c5d93e | |||
| c4603ee5cd | |||
| 1e9d1007b6 | |||
| f23af85253 | |||
| b0c5d16ba7 | |||
| cd5581bef6 | |||
| 7d8da56dcb | |||
| 0501b181ce | |||
| 6d076a09e4 | |||
| 3cd3230b55 | |||
| 3134668cec | |||
| a8cc8fa688 | |||
| cf2217cfe1 | |||
| e88e809e29 | |||
| b404f3b56b | |||
| c5559d7721 | |||
| e9da4121bd | |||
| 771e216813 | |||
| 877ae6e026 | |||
| e1d99855f6 | |||
| 9d9db577b4 | |||
| b4127294e5 | |||
| d369af5fe0 | |||
| 74dd1f9181 | |||
| 86f7d79e7a | |||
| c1781c2f4b | |||
| d0dae43dd1 | |||
| 90bf600378 | |||
| d33cc29f98 | |||
| 472c9d3a88 | |||
| e23d7d1af3 | |||
| 4b97eb2a9a | |||
| dadf063ad5 | |||
| 86e18ef89d | |||
| e0c3eda675 | |||
| b98fbbc75d | |||
| aba1862811 | |||
| 470913f796 | |||
| 2f53698bc5 | |||
| e0e12d5773 | |||
| 2e96de5449 | |||
| c5bce3b8cc | |||
| b4286a7d4e | |||
| 31e018c045 | |||
| e964d52548 | |||
| 50b71faff9 | |||
| d7bd38386e | |||
| 1f581c1fcb | |||
| 475e6970f9 | |||
| 32c8a83449 | |||
| 33ee2a4e48 | |||
| b420941ff4 | |||
| 033fd1b7ff | |||
| 5f0b09544a | |||
| 7aa618cbfb | |||
| 44fbc29541 | |||
| e3162d223d | |||
| 6e53e19e60 | |||
| d9ac529e7e | |||
| 2621b25fd3 | |||
| 61055380c5 | |||
| adf09d925f | |||
| 12170fd787 | |||
| c32cae16db | |||
| 437d1b759b | |||
| e10e04aabf | |||
| 2c1807bb37 | |||
| c6e3340be1 | |||
| 3bac4877eb | |||
| f46811ff67 | |||
| ee210ae5d8 | |||
| 6d50b46bd8 | |||
| 0810e90478 | |||
| e8989de82e | |||
| a51bf232ec | |||
| cefc319bfb | |||
| b60ee9944d | |||
| 0d8ffc0e67 | |||
| fd19411e65 | |||
| 7ac7bb9714 | |||
| 95cd32ad8c | |||
| 021cac9ca5 | |||
| aaa56002a9 | |||
| c00c59af1d | |||
| 56d949ab9d | |||
| 65ecff4248 | |||
| 9c82e8bc8c | |||
| 421162d809 | |||
| 360c324511 | |||
| 949447c25f | |||
| 99d7bf91b7 | |||
| cc3a6f8c7a | |||
| 9bbe8e7a93 | |||
| 508a40cd50 | |||
| a92c232178 | |||
| 30901446e1 | |||
| e42149e8d9 | |||
| a4949a1132 | |||
| 0725d95941 | |||
| d772336c0f | |||
| 4f8485e7d9 | |||
| f673cb024a | |||
| c4046ecb32 | |||
| b978582675 | |||
| 7823609500 | |||
| 069ae9930a | |||
| 509d3f2647 | |||
| a88cb3f724 | |||
| 2881118a02 | |||
| 464cfb34f2 | |||
| 7a04881428 | |||
| 8556cf5702 | |||
| 1c0038ead3 | |||
| ef787fc769 | |||
| ec04469b16 | |||
| 80db81a7c5 | |||
| 7787c51156 | |||
| 1a02e6be97 | |||
| 536b8ee921 | |||
| 12acdd8122 | |||
| 3bf1041041 | |||
| cd459e8b7d | |||
| 7ae522b511 | |||
| 1cf20597a4 | |||
| e8d41a1b5e | |||
| 9a14a29a53 | |||
| d66998a3e3 | |||
| fe4da60b15 | |||
| 52186f5cb2 | |||
| b13251778e | |||
| 51309e62ec | |||
| fee23fac0a | |||
| 15f4de4ed0 | |||
| 8c303893d2 | |||
| 7d556a0318 | |||
| cf6775ec31 | |||
| 1a13366cc9 | |||
| 595b039ebe | |||
| e6406e9757 | |||
| bf65bf5bab | |||
| a39a659858 | |||
| 306d83cbd6 | |||
| a4eedb9f8b | |||
| 1da901be96 | |||
| d953966248 | |||
| 2f679a52f4 | |||
| ad8ab9f46e | |||
| 9b344a5a69 | |||
| 0a28bdafc2 | |||
| a3a0f1a0bf | |||
| f69527eac1 | |||
| 7aa1f480c9 | |||
| 998f031877 | |||
| ac7cb8febe | |||
| 6e166bdba7 | |||
| 1f2e46a195 | |||
| bb22f5a283 | |||
| 4890e97168 | |||
| e4f63c0576 | |||
| dcac5d4709 | |||
| 0e4e12d0ba | |||
| 9118701669 | |||
| 58758e7a41 | |||
| 1eaf02b221 | |||
| 5697809ce9 | |||
| 4f5cae55c2 | |||
| e5b4769109 | |||
| 5990a95d13 | |||
| e3c4ed5bf7 | |||
| 02a4c2f4fc | |||
| b60aa3031c | |||
| 2a0e3d803f | |||
| 670a67225a | |||
| 0bedf09f48 | |||
| 41ad18deef | |||
| 4745be4765 | |||
| 13891bb033 | |||
| a2efd7ab53 | |||
| 3c204da150 | |||
| ab7371e146 | |||
| 0f5c79afbc | |||
| 4a516f7da9 | |||
| fcb080658d | |||
| f45edbe2fe | |||
| 08d74e3320 | |||
| 98fd75b55d | |||
| e7da70e076 | |||
| 200cec0e23 | |||
| 807778a737 | |||
| 66d61c9d20 | |||
| ecae5a856a | |||
| bf8add4f8d | |||
| 256fa3385a | |||
| ebaa46b2fc | |||
| e207185d51 | |||
| 5efc45a7dd | |||
| c3fc27565d | |||
| 0af3f9dce0 | |||
| 426b02b08a | |||
| a4e23ef82b | |||
| d0c6c4aafa | |||
| 3ea7e6fb8a | |||
| 9940b78a57 | |||
| 8371105c10 | |||
| d4b0f3c570 | |||
| 29416320d2 | |||
| d11eb485e1 | |||
| 300bd3bed4 | |||
| 3ca5443350 | |||
| f6d56f51d4 | |||
| 53c0bd6938 | |||
| 174aa9f4ad | |||
| a768fe5bb3 | |||
| d9c66cd4b3 | |||
| 6d3e8e1f6d | |||
| b6185b847f | |||
| c8877d0a2c | |||
| 891810b045 | |||
| 77d910b6b6 | |||
| 47044b3a77 | |||
| 5b693f9310 | |||
| 40ebc1295c | |||
| b769b224c2 | |||
| 89efe40f41 | |||
| 51660d918c | |||
| ea7b053106 | |||
| 3e17201ce7 | |||
| 1f03983628 | |||
| 15aa6fc4b8 | |||
| 41e8a9ef2d | |||
| a492976a32 | |||
| 88e09f9077 | |||
| 65a1709bd3 | |||
| 6478a8424a | |||
| 55ade4e491 | |||
| a767aa9f3a | |||
| 50321e5936 | |||
| 1321702d19 | |||
| 005ff2f830 | |||
| dff3fde840 | |||
| 44504ff6af | |||
| 25d3389759 | |||
| 3f97c74712 | |||
| 1152b61fb0 | |||
| b1842de045 | |||
| 750a2862ee | |||
| 7632075df4 | |||
| aa75cd4ea8 | |||
| 06827bd7a5 | |||
| 9a82ab7d4a | |||
| b1037d1936 | |||
| ccdc3a1eab | |||
| 655d629621 | |||
| c8e0fedce4 | |||
| a47387fec0 | |||
| c29d08c915 | |||
| b8f796eb2c | |||
| b9088c9ac0 | |||
| 7a8f8ac0fe | |||
| 49cf0f98ce | |||
| 22ffa86e18 | |||
| c4e2d98138 | |||
| c01211c62d | |||
| d8a3e00440 | |||
| 264c537b50 | |||
| f26c61d736 | |||
| 43f647fd94 | |||
| cc0bcc2d59 | |||
| 1b23540b87 | |||
| c309e18f13 | |||
| dec60885b4 | |||
| eee09ec45b | |||
| b4daab2856 | |||
| fdfbad254d | |||
| 0c6e766030 | |||
| 7444363cef | |||
| a82097b92b | |||
| 07934161a4 | |||
| 9194030a9a | |||
| 1cbaace777 | |||
| ef5052324b | |||
| 204a8d813c | |||
| 8009cb3892 | |||
| 284d168cd7 | |||
| fdd025aefd | |||
| e36d4768e1 | |||
| df2047e8f8 | |||
| d9280d5238 | |||
| 388249f500 | |||
| a08b75592e | |||
| 38ea6dfbfe | |||
| 39ccde221a | |||
| 17b6366ea3 | |||
| 3d6a608b12 | |||
| 851f58df9c | |||
| 0ff0cc6366 | |||
| 08004ecc68 | |||
| 4a2544d0e6 | |||
| bace1cce74 | |||
| acc88e25d8 | |||
| 2a1a16d478 | |||
| a5afb8ed19 | |||
| d02678e05c | |||
| 9e0bbd3c99 | |||
| 539efcc669 | |||
| d0d9d85151 | |||
| ffa307613c | |||
| 19ea6d6005 | |||
| 155b1737d3 | |||
| b66253f33e | |||
| bcbadfe648 | |||
| 3325b06873 | |||
| 852914bf6b | |||
| 3e14807370 | |||
| e44cb6708d | |||
| fd43b27d00 | |||
| 524f113611 | |||
| 04dcf50218 | |||
| 2b497deaa3 | |||
| dbe2f8ea37 | |||
| 7dc0239ad1 | |||
| 72fdc5f472 | |||
| cde3c42cec | |||
| 10b544abb9 | |||
| 88aecdf672 | |||
| ad95736eaa | |||
| 34a21a78a0 | |||
| 1e01c2669f | |||
| d3a7389b89 | |||
| bc8b6c4bea | |||
| 3953a48a3b | |||
| 2f44e94bd0 | |||
| 5eeb8d7df6 | |||
| 231f23cc6e | |||
| 3235678d29 | |||
| f13ddddc16 | |||
| 490c346fcf | |||
| 8f1d8419a0 | |||
| be8320bb4b | |||
| 1d4b6178e5 | |||
| 3427f596e3 | |||
| c31ea7409f | |||
| f88e60bcb5 | |||
| c81919e269 | |||
| c936aaa517 | |||
| b8f88e0459 | |||
| 1628ac917c | |||
| ab586a49ce | |||
| ff2ee540e2 | |||
| b450299d45 | |||
| 0ebe535922 | |||
| f5f8fe7b42 | |||
| f51a66b728 | |||
| f8a7b453c7 | |||
| 89235f707c | |||
| 550166c41b | |||
| 40be3957f6 | |||
| 6ccce4d914 | |||
| 14ea374b24 | |||
| 4d49268c47 | |||
| a569796adb | |||
| 59de0613f5 | |||
| 8391c32886 | |||
| bf2efd30e9 | |||
| 187373132f | |||
| 79584a9cf9 | |||
| 96fa8c7dc9 | |||
| 5e43ddc13c | |||
| 98f76a989f | |||
| 2e8993adb8 | |||
| 81600f0f3c | |||
| 74ccd79408 | |||
| 3e0a754dc0 | |||
| 006a89e136 | |||
| 29dbbee173 | |||
| cd31637371 | |||
| ab70c98d4c | |||
| 424ff02734 | |||
| 80bd8d962b | |||
| 956364decd | |||
| 6133e8f8c2 | |||
| b048ae4d36 | |||
| b7f7775b89 | |||
| 6eeb9d6af4 | |||
| cbefabb724 | |||
| f7f6cc64ce | |||
| 1408e4f64e | |||
| 0a68d2f4ee | |||
| 11a4a0436d | |||
| 2583800b2c |
+2
-1
@@ -108,4 +108,5 @@ src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
|
||||
src/Umbraco.Web.UI/umbraco/plugins/*
|
||||
src/Umbraco.Web.UI/umbraco/js/init.js
|
||||
build/ApiDocs/*
|
||||
build/ApiDocs/Output/*
|
||||
build/ApiDocs/Output/*
|
||||
src/Umbraco.Web.UI.Client/bower_components/*
|
||||
|
||||
+9
-5
@@ -1,6 +1,6 @@
|
||||
@ECHO OFF
|
||||
SET release=7.1.0
|
||||
SET comment=RC
|
||||
SET release=7.1.2
|
||||
SET comment=
|
||||
SET version=%release%
|
||||
|
||||
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
|
||||
@@ -12,6 +12,9 @@ ECHO Installing the Microsoft.Bcl.Build package before anything else, otherwise
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder%
|
||||
|
||||
ECHO Removing the belle build folder to make sure everything is clean as a whistle
|
||||
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
|
||||
|
||||
ECHO Performing MSBuild and producing Umbraco binaries zip files
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
|
||||
@@ -30,11 +33,12 @@ echo This file is only here so that the containing folder will be included in th
|
||||
ECHO Adding Web.config transform files to the NuGet package
|
||||
ren .\_BuildOutput\WebApp\MacroScripts\Web.config Web.config.transform
|
||||
ren .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
|
||||
ren .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
|
||||
|
||||
ECHO Packing the NuGet release files
|
||||
..\src\.nuget\NuGet.exe pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
|
||||
..\src\.nuget\NuGet.exe pack NuSpecs\UmbracoCms.nuspec -Version %version%
|
||||
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version%
|
||||
|
||||
IF ERRORLEVEL 1 GOTO :showerror
|
||||
|
||||
GOTO :EOF
|
||||
|
||||
+11
-1
@@ -310,7 +310,12 @@
|
||||
</Target>
|
||||
|
||||
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
|
||||
<!-- Match & replace 3 and 4 digit version numbers and -beta (if it's there) -->
|
||||
<PropertyGroup>
|
||||
<NewVersion>$(BUILD_RELEASE)</NewVersion>
|
||||
<NewVersion Condition="'$(BUILD_COMMENT)'!=''">$(BUILD_RELEASE)-$(BUILD_COMMENT)</NewVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Match & replace 3 and 4 digit version numbers and -beta (if it's there) -->
|
||||
<FileUpdate
|
||||
Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
|
||||
Regex="(\d+)\.(\d+)\.(\d+)(.(\d+))?"
|
||||
@@ -319,5 +324,10 @@
|
||||
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
|
||||
Regex="CurrentComment { get { return "([a-zA-Z]+)?""
|
||||
ReplacementText="CurrentComment { get { return "$(BUILD_COMMENT)""/>
|
||||
|
||||
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.targets"
|
||||
Namespaces="<Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' />"
|
||||
Query="//x:UmbracoVersion"
|
||||
Value="$(NewVersion)" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -15,6 +15,8 @@ SET oldPath=%PATH%
|
||||
|
||||
path=%npmPath%;%nodePath%;%PATH%
|
||||
|
||||
ECHO %path%
|
||||
|
||||
SET buildFolder=%CD%
|
||||
|
||||
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
@@ -23,7 +25,8 @@ CD %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
ECHO Do npm install and the grunt build of Belle
|
||||
call npm install
|
||||
call npm install -g grunt-cli
|
||||
call grunt build
|
||||
call npm install -g bower
|
||||
call grunt build --buildversion=7.1.2
|
||||
|
||||
ECHO Reset path to what it was before
|
||||
path=%oldPath%
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoCms.Core.AllBinaries</id>
|
||||
<version>6.1.2</version>
|
||||
<title>Umbraco Cms Core All Binaries</title>
|
||||
<authors>Morten Christensen</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://umbraco.codeplex.com/license</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies and all of the dependant assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies and all of the dependant assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\_BuildOutput\bin\businesslogic.dll" target="lib\businesslogic.dll" />
|
||||
<file src="..\_BuildOutput\bin\AutoMapper.dll" target="lib\AutoMapper.dll" />
|
||||
<file src="..\_BuildOutput\bin\AutoMapper.Net4.dll" target="lib\AutoMapper.Net4.dll" />
|
||||
<file src="..\_BuildOutput\bin\businesslogic.dll" target="lib\businesslogic.dll" />
|
||||
<file src="..\_BuildOutput\bin\ClientDependency.Core.dll" target="lib\ClientDependency.Core.dll" />
|
||||
<file src="..\_BuildOutput\bin\ClientDependency.Core.Mvc.dll" target="lib\ClientDependency.Core.Mvc.dll" />
|
||||
<file src="..\_BuildOutput\bin\cms.dll" target="lib\cms.dll" />
|
||||
<file src="..\_BuildOutput\bin\controls.dll" target="lib\controls.dll" />
|
||||
<file src="..\_BuildOutput\bin\CookComputing.XmlRpcV2.dll" target="lib\CookComputing.XmlRpcV2.dll" />
|
||||
<file src="..\_BuildOutput\bin\Examine.dll" target="lib\Examine.dll" />
|
||||
<file src="..\_BuildOutput\bin\HtmlAgilityPack.dll" target="lib\HtmlAgilityPack.dll" />
|
||||
<file src="..\_BuildOutput\bin\ICSharpCode.SharpZipLib.dll" target="lib\ICSharpCode.SharpZipLib.dll" />
|
||||
<file src="..\_BuildOutput\bin\ImageProcessor.dll" target="lib\ImageProcessor.dll" />
|
||||
<file src="..\_BuildOutput\bin\ImageProcessor.Web.dll" target="lib\ImageProcessor.Web.dll" />
|
||||
<file src="..\_BuildOutput\bin\interfaces.dll" target="lib\interfaces.dll" />
|
||||
<file src="..\_BuildOutput\bin\log4net.dll" target="lib\log4net.dll" />
|
||||
<file src="..\_BuildOutput\bin\Lucene.Net.dll" target="lib\Lucene.Net.dll" />
|
||||
<file src="..\_BuildOutput\bin\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
|
||||
<file src="..\_BuildOutput\bin\Microsoft.Threading.Tasks.dll" target="lib\Microsoft.Threading.Tasks.dll" />
|
||||
<file src="..\_BuildOutput\bin\Microsoft.Threading.Tasks.Extensions.dll" target="lib\Microsoft.Threading.Tasks.Extensions.dll" />
|
||||
<file src="..\_BuildOutput\bin\Microsoft.Web.Helpers.dll" target="lib\Microsoft.Web.Helpers.dll" />
|
||||
<file src="..\_BuildOutput\bin\Microsoft.Web.Infrastructure.dll" target="lib\Microsoft.Web.Infrastructure.dll" />
|
||||
<file src="..\_BuildOutput\bin\Microsoft.Web.Mvc.FixedDisplayModes.dll" target="lib\Microsoft.Web.Mvc.FixedDisplayModes.dll" />
|
||||
<file src="..\_BuildOutput\bin\MiniProfiler.dll" target="lib\MiniProfiler.dll" />
|
||||
<file src="..\_BuildOutput\bin\MySql.Data.dll" target="lib\MySql.Data.dll" />
|
||||
<file src="..\_BuildOutput\bin\Newtonsoft.Json.dll" target="lib\Newtonsoft.Json.dll" />
|
||||
<file src="..\_BuildOutput\bin\NuGet.Core.dll" target="lib\NuGet.Core.dll" />
|
||||
<file src="..\_BuildOutput\bin\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Net.Http.dll" target="lib\System.Net.Http.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Net.Http.Extensions.dll" target="lib\System.Net.Http.Extensions.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Net.Http.Formatting.dll" target="lib\System.Net.Http.Formatting.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Net.Http.Primitives.dll" target="lib\System.Net.Http.Primitives.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Net.Http.WebRequest.dll" target="lib\System.Net.Http.WebRequest.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.Helpers.dll" target="lib\System.Web.Helpers.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.Http.dll" target="lib\System.Web.Http.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.Http.WebHost.dll" target="lib\System.Web.Http.WebHost.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.Mvc.dll" target="lib\System.Web.Mvc.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.Razor.dll" target="lib\System.Web.Razor.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.WebPages.Administration.dll" target="lib\System.Web.WebPages.Administration.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.WebPages.Deployment.dll" target="lib\System.Web.WebPages.Deployment.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.WebPages.dll" target="lib\System.Web.WebPages.dll" />
|
||||
<file src="..\_BuildOutput\bin\System.Web.WebPages.Razor.dll" target="lib\System.Web.WebPages.Razor.dll" />
|
||||
<file src="..\_BuildOutput\bin\TidyNet.dll" target="lib\TidyNet.dll" />
|
||||
<file src="..\_BuildOutput\bin\Umbraco.Core.dll" target="lib\Umbraco.Core.dll" />
|
||||
<file src="..\_BuildOutput\bin\umbraco.DataLayer.dll" target="lib\umbraco.DataLayer.dll" />
|
||||
<file src="..\_BuildOutput\bin\umbraco.dll" target="lib\umbraco.dll" />
|
||||
<file src="..\_BuildOutput\bin\umbraco.editorControls.dll" target="lib\umbraco.editorControls.dll" />
|
||||
<file src="..\_BuildOutput\bin\umbraco.MacroEngines.dll" target="lib\umbraco.MacroEngines.dll" />
|
||||
<file src="..\_BuildOutput\bin\umbraco.providers.dll" target="lib\umbraco.providers.dll" />
|
||||
<file src="..\_BuildOutput\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
|
||||
<file src="..\_BuildOutput\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
|
||||
<file src="..\_BuildOutput\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>7.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://umbraco.codeplex.com/license</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\..\src\SQLCE4Umbraco\obj\Debug\SQLCE4Umbraco.dll" target="lib" />
|
||||
<file src="..\..\src\SQLCE4Umbraco\obj\Debug\SQLCE4Umbraco.pdb" target="lib" />
|
||||
<file src="..\..\src\SQLCE4Umbraco\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\SQLCE4Umbraco" />
|
||||
|
||||
<file src="..\..\src\umbraco.businesslogic\obj\Debug\businesslogic.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.businesslogic\obj\Debug\businesslogic.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.businesslogic\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.businesslogic" />
|
||||
|
||||
<file src="..\..\src\umbraco.cms\obj\Debug\cms.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.cms\obj\Debug\cms.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.cms\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.cms" />
|
||||
|
||||
<file src="..\..\src\umbraco.controls\obj\Debug\controls.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.controls\obj\Debug\controls.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.controls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.controls" />
|
||||
|
||||
<file src="..\..\src\umbraco.interfaces\obj\Debug\interfaces.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.interfaces\obj\Debug\interfaces.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.interfaces\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.interfaces" />
|
||||
|
||||
<file src="..\..\src\Umbraco.Core\obj\Debug\Umbraco.Core.dll" target="lib" />
|
||||
<file src="..\..\src\Umbraco.Core\obj\Debug\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="..\..\src\Umbraco.Core\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
|
||||
<file src="..\..\src\umbraco.datalayer\obj\Debug\umbraco.DataLayer.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.datalayer\obj\Debug\umbraco.DataLayer.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.datalayer\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.datalayer" />
|
||||
|
||||
<file src="..\..\src\umbraco.editorControls\obj\Debug\umbraco.editorControls.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.editorControls\obj\Debug\umbraco.editorControls.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.editorControls\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.editorControls" />
|
||||
|
||||
<file src="..\..\src\umbraco.MacroEngines\obj\Debug\umbraco.MacroEngines.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.MacroEngines\obj\Debug\umbraco.MacroEngines.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.MacroEngines\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.MacroEngines" />
|
||||
|
||||
<file src="..\..\src\umbraco.providers\obj\Debug\umbraco.providers.dll" target="lib" />
|
||||
<file src="..\..\src\umbraco.providers\obj\Debug\umbraco.providers.pdb" target="lib" />
|
||||
<file src="..\..\src\umbraco.providers\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\umbraco.providers" />
|
||||
|
||||
<file src="..\..\src\Umbraco.Web\obj\Debug\umbraco.dll" target="lib" />
|
||||
<file src="..\..\src\Umbraco.Web\obj\Debug\umbraco.pdb" target="lib" />
|
||||
<file src="..\..\src\Umbraco.Web\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
|
||||
<file src="..\..\src\bin\Debug\Umbraco.Web.UI.dll" target="lib" />
|
||||
<file src="..\..\src\bin\Debug\Umbraco.Web.UI.pdb" target="lib" />
|
||||
<file src="..\..\src\Umbraco.Web.UI\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
|
||||
|
||||
<file src="..\..\src\UmbracoExamine\obj\Debug\UmbracoExamine.dll" target="lib" />
|
||||
<file src="..\..\src\UmbracoExamine\obj\Debug\UmbracoExamine.pdb" target="lib" />
|
||||
<file src="..\..\src\UmbracoExamine\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\UmbracoExamine" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -26,12 +26,12 @@
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.6.5]" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.7.0, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc" version="[1.7.0, 2.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.7.1.2, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc" version="[1.7.0.4, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.0.0, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[4.5.11, 5.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.8.6.1, 2.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.2.0, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.2, 7.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.9.0, 2.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.2.3, 4.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<metadata minClientVersion="2.8">
|
||||
<id>UmbracoCms</id>
|
||||
<version>7.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<UmbracoVersion>7.1.2</UmbracoVersion>
|
||||
</PropertyGroup>
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<PropertyGroup>
|
||||
<UmbracoFilesFolder>..\packages\UmbracoCms.$(UmbracoVersion)\UmbracoFiles\</UmbracoFilesFolder>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include="$(UmbracoFilesFolder)**\*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="%(UmbracoFiles.FullPath)" DestinationFiles="%(RecursiveDir)%(Filename)%(Extension)" Condition="!Exists('%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<!-- With help from: http://blog.samstephens.co.nz/2010-10-18/msbuild-including-extra-files-multiple-builds/ -->
|
||||
<ItemGroup>
|
||||
<CustomFilesToInclude Include=".\App_Browsers\**\*">
|
||||
<Dir>App_Browsers</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\App_Code\**\*">
|
||||
<Dir>App_Code</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\App_Plugins\**\*">
|
||||
<Dir>App_Plugins</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\bin\amd64\**\*">
|
||||
<Dir>bin\amd64</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\bin\x86\**\*">
|
||||
<Dir>bin\x86</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\Config\Splashes\**\*">
|
||||
<Dir>Config\Splashes</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco\**\*">
|
||||
<Dir>umbraco</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco_client\**\*">
|
||||
<Dir>umbraco_client</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\Global.asax">
|
||||
<Dir>.</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<FilesForPackagingFromProject Include="@(CustomFilesToInclude)">
|
||||
<DestinationRelativePath>%(CustomFilesToInclude.Dir)\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,72 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<ItemGroup>
|
||||
<AppBrowsersFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\App_Browsers\**\*" />
|
||||
<AppPluginsFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\App_Plugins\**\*" />
|
||||
<SplashesFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\Config\Splashes\**\*;" />
|
||||
<SqlCeBinFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\bin\**\*;" />
|
||||
<UmbracoFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\umbraco_client\**\*;" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="%(AppBrowsersFiles.FullPath)"
|
||||
DestinationFiles="App_Browsers\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('App_Browsers\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(AppPluginsFiles.FullPath)"
|
||||
DestinationFiles="App_Plugins\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('App_Plugins\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(SplashesFiles.FullPath)"
|
||||
DestinationFiles="Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(SqlCeBinFiles.FullPath)"
|
||||
DestinationFiles="bin\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('bin\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(UmbracoFiles.FullPath)"
|
||||
DestinationFiles="umbraco\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('umbraco\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(UmbracoClientFiles.FullPath)"
|
||||
DestinationFiles="umbraco_client\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('umbraco_client\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<ItemGroup>
|
||||
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
|
||||
<AppCodeFiles Include=".\App_Code\**\*" />
|
||||
<AppPluginsFiles Include=".\App_Plugins\**\*" />
|
||||
<GlobalAsaxFile Include=".\Global.asax;" />
|
||||
<SqlCeAmd64Files Include=".\bin\amd64\**\*" />
|
||||
<SqlCeX86Files Include=".\bin\x86\**\*" />
|
||||
<SplashesFiles Include=".\Config\Splashes\**\*;" />
|
||||
<UmbracoFiles Include=".\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
|
||||
|
||||
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
|
||||
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppCodeFiles.Identity)">
|
||||
<DestinationRelativePath>App_Code\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppPluginsFiles.Identity)">
|
||||
<DestinationRelativePath>App_Plugins\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(GlobalAsaxFile.Identity)">
|
||||
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SqlCeAmd64Files.Identity)">
|
||||
<DestinationRelativePath>bin\amd64\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SqlCeX86Files.Identity)">
|
||||
<DestinationRelativePath>bin\x86\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SplashesFiles.Identity)">
|
||||
<DestinationRelativePath>Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,72 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<ItemGroup>
|
||||
<AppBrowsersFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\App_Browsers\**\*" />
|
||||
<AppPluginsFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\App_Plugins\**\*" />
|
||||
<SplashesFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\Config\Splashes\**\*;" />
|
||||
<SqlCeBinFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\bin\**\*;" />
|
||||
<UmbracoFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\umbraco_client\**\*;" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="%(AppBrowsersFiles.FullPath)"
|
||||
DestinationFiles="App_Browsers\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('App_Browsers\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(AppPluginsFiles.FullPath)"
|
||||
DestinationFiles="App_Plugins\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('App_Plugins\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(SplashesFiles.FullPath)"
|
||||
DestinationFiles="Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(SqlCeBinFiles.FullPath)"
|
||||
DestinationFiles="bin\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('bin\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(UmbracoFiles.FullPath)"
|
||||
DestinationFiles="umbraco\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('umbraco\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(UmbracoClientFiles.FullPath)"
|
||||
DestinationFiles="umbraco_client\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('umbraco_client\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<ItemGroup>
|
||||
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
|
||||
<AppCodeFiles Include=".\App_Code\**\*" />
|
||||
<AppPluginsFiles Include=".\App_Plugins\**\*" />
|
||||
<GlobalAsaxFile Include=".\Global.asax;" />
|
||||
<SqlCeAmd64Files Include=".\bin\amd64\**\*" />
|
||||
<SqlCeX86Files Include=".\bin\x86\**\*" />
|
||||
<SplashesFiles Include=".\Config\Splashes\**\*;" />
|
||||
<UmbracoFiles Include=".\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
|
||||
|
||||
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
|
||||
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppCodeFiles.Identity)">
|
||||
<DestinationRelativePath>App_Code\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppPluginsFiles.Identity)">
|
||||
<DestinationRelativePath>App_Plugins\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(GlobalAsaxFile.Identity)">
|
||||
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SqlCeAmd64Files.Identity)">
|
||||
<DestinationRelativePath>bin\amd64\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SqlCeX86Files.Identity)">
|
||||
<DestinationRelativePath>bin\x86\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SplashesFiles.Identity)">
|
||||
<DestinationRelativePath>Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,72 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<ItemGroup>
|
||||
<AppBrowsersFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\App_Browsers\**\*" />
|
||||
<AppPluginsFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\App_Plugins\**\*" />
|
||||
<SplashesFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\Config\Splashes\**\*;" />
|
||||
<SqlCeBinFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\bin\**\*;" />
|
||||
<UmbracoFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include="..\packages\UmbracoCms.7.1.0-RC\UmbracoFiles\umbraco_client\**\*;" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="%(AppBrowsersFiles.FullPath)"
|
||||
DestinationFiles="App_Browsers\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('App_Browsers\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(AppPluginsFiles.FullPath)"
|
||||
DestinationFiles="App_Plugins\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('App_Plugins\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(SplashesFiles.FullPath)"
|
||||
DestinationFiles="Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(SqlCeBinFiles.FullPath)"
|
||||
DestinationFiles="bin\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('bin\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(UmbracoFiles.FullPath)"
|
||||
DestinationFiles="umbraco\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('umbraco\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
<Copy SourceFiles="%(UmbracoClientFiles.FullPath)"
|
||||
DestinationFiles="umbraco_client\%(RecursiveDir)%(Filename)%(Extension)"
|
||||
Condition="!Exists('umbraco_client\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
<Target Name="AddUmbracoFilesToOutput">
|
||||
<ItemGroup>
|
||||
<AppBrowsersFiles Include=".\App_Browsers\**\*" />
|
||||
<AppCodeFiles Include=".\App_Code\**\*" />
|
||||
<AppPluginsFiles Include=".\App_Plugins\**\*" />
|
||||
<GlobalAsaxFile Include=".\Global.asax;" />
|
||||
<SqlCeAmd64Files Include=".\bin\amd64\**\*" />
|
||||
<SqlCeX86Files Include=".\bin\x86\**\*" />
|
||||
<SplashesFiles Include=".\Config\Splashes\**\*;" />
|
||||
<UmbracoFiles Include=".\umbraco\**\*;" />
|
||||
<UmbracoClientFiles Include=".\umbraco_client\**\*;" />
|
||||
|
||||
<FilesForPackagingFromProject Include="%(AppBrowsersFiles.Identity)">
|
||||
<DestinationRelativePath>App_Browsers\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppCodeFiles.Identity)">
|
||||
<DestinationRelativePath>App_Code\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(AppPluginsFiles.Identity)">
|
||||
<DestinationRelativePath>App_Plugins\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(GlobalAsaxFile.Identity)">
|
||||
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SqlCeAmd64Files.Identity)">
|
||||
<DestinationRelativePath>bin\amd64\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SqlCeX86Files.Identity)">
|
||||
<DestinationRelativePath>bin\x86\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(SplashesFiles.Identity)">
|
||||
<DestinationRelativePath>Config\Splashes\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
<FilesForPackagingFromProject Include="%(UmbracoClientFiles.Identity)">
|
||||
<DestinationRelativePath>umbraco_client\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -2,10 +2,15 @@ A note about running Umbraco from Visual Studio.
|
||||
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
We will overwrite Web.config anyway but we keep a backup in the App_Data\ConfigBackup folder. There you'll
|
||||
We will overwrite Web.config anyway but we keep a backup in the App_Data\NuGetBackup folder. There you'll
|
||||
find a folder with the current date and time in which the backup has been placed. Make sure to merge the
|
||||
new file with the old backup files before you proceed.
|
||||
Only the web.config will be overwritten by default to ensure that it has the necessary settings from the current release.
|
||||
The web.config will be overwritten by default to ensure that it has the necessary settings from the current release.
|
||||
|
||||
We've also overwritten all the files in the Umbraco and Umbraco_Client folder, these have also been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or a package
|
||||
might have added. Only the existing files were overwritten. If you customized anything then make sure to do a compare
|
||||
and merge with the NuGetBackup folder.
|
||||
|
||||
The config files found in the config folder will usually not be changed for patch releases, so they can usually be skipped,
|
||||
but the web.config will have to have its previous "umbracoConfigurationStatus"-appsetting and "umbracoDbDSN" connection string
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
param($rootPath, $toolsPath, $package, $project)
|
||||
|
||||
if ($project) {
|
||||
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
|
||||
$backupPath = Join-Path (Split-Path $project.FullName -Parent) "\App_Data\ConfigBackup\$dateTime"
|
||||
if ($project) {
|
||||
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
|
||||
$backupPath = Join-Path (Split-Path $project.FullName -Parent) "\App_Data\NuGetBackup\$dateTime"
|
||||
$copyLogsPath = Join-Path $backupPath "CopyLogs"
|
||||
|
||||
# Create backup folder if it doesn't exist yet
|
||||
# Create backup folder and logs folder if it doesn't exist yet
|
||||
New-Item -ItemType Directory -Force -Path $backupPath
|
||||
New-Item -ItemType Directory -Force -Path $copyLogsPath
|
||||
|
||||
# Create a backup of original web.config
|
||||
$projectDestinationPath = Split-Path $project.FullName -Parent
|
||||
@@ -15,7 +17,32 @@ if ($project) {
|
||||
# Copy Web.config from package to project folder
|
||||
$umbracoFilesPath = Join-Path $rootPath "UmbracoFiles\Web.config"
|
||||
Copy-Item $umbracoFilesPath $projectDestinationPath -Force
|
||||
|
||||
|
||||
# Copy umbraco and umbraco_files from package to project folder
|
||||
# This is only done when these folders already exist because we
|
||||
# only want to do this for upgrades
|
||||
$umbracoFolder = Join-Path $projectDestinationPath "Umbraco"
|
||||
if(Test-Path $umbracoFolder) {
|
||||
$umbracoFolderSource = Join-Path $rootPath "UmbracoFiles\Umbraco"
|
||||
|
||||
$umbracoBackupPath = Join-Path $backupPath "Umbraco"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBackupPath
|
||||
|
||||
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
}
|
||||
|
||||
$umbracoClientFolder = Join-Path $projectDestinationPath "Umbraco_Client"
|
||||
if(Test-Path $umbracoClientFolder) {
|
||||
$umbracoClientFolderSource = Join-Path $rootPath "UmbracoFiles\Umbraco_Client"
|
||||
|
||||
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
|
||||
|
||||
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
|
||||
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
|
||||
}
|
||||
|
||||
# Open readme.txt file
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\Readme.txt')
|
||||
}
|
||||
Binary file not shown.
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core
|
||||
|
||||
@@ -53,5 +53,6 @@ namespace Umbraco.Core.Cache
|
||||
public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty";
|
||||
|
||||
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
|
||||
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,12 @@ namespace Umbraco.Core.Cache
|
||||
return result.Select(x => x.TryConvertTo<T>().Result);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCacheItemsByKeyExpression<T>(this ICacheProvider provider, string regexString)
|
||||
{
|
||||
var result = provider.GetCacheItemsByKeyExpression(regexString);
|
||||
return result.Select(x => x.TryConvertTo<T>().Result);
|
||||
}
|
||||
|
||||
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey);
|
||||
|
||||
@@ -171,6 +171,26 @@ namespace Umbraco.Core.Cache
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
var found = new List<object>();
|
||||
foreach (var item in DictionaryCache)
|
||||
{
|
||||
var c = new DictionaryItemWrapper(item);
|
||||
var s = c.Key as string;
|
||||
if (s != null)
|
||||
{
|
||||
var withoutPrefix = s.TrimStart(string.Format("{0}-", CacheItemPrefix));
|
||||
if (Regex.IsMatch(withoutPrefix, regexString))
|
||||
{
|
||||
found.Add(c.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a cache item by key, does not update the cache if it isn't there.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,7 +16,15 @@ namespace Umbraco.Core.Cache
|
||||
void ClearCacheByKeySearch(string keyStartsWith);
|
||||
void ClearCacheByKeyExpression(string regexString);
|
||||
IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith);
|
||||
IEnumerable<object> GetCacheItemsByKeyExpression(string regexString);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an item with a given key
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <returns></returns>
|
||||
object GetCacheItem(string cacheKey);
|
||||
|
||||
object GetCacheItem(string cacheKey, Func<object> getCacheItem);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,11 @@ namespace Umbraco.Core.Cache
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
return default(object);
|
||||
|
||||
@@ -114,6 +114,13 @@ namespace Umbraco.Core.Cache
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return (from c in MemoryCache
|
||||
where Regex.IsMatch(c.Key, regexString)
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
var result = MemoryCache.Get(cacheKey);
|
||||
|
||||
@@ -59,6 +59,13 @@ namespace Umbraco.Core.Cache
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return (from KeyValuePair<string, object> c in StaticCache
|
||||
where Regex.IsMatch(c.Key, regexString)
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
var result = StaticCache[cacheKey];
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.1.0");
|
||||
private static readonly Version Version = new Version("7.1.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
@@ -23,7 +23,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 "RC"; } }
|
||||
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
|
||||
|
||||
@@ -149,7 +149,14 @@ namespace Umbraco.Core
|
||||
/// <param name="connectionString"></param>
|
||||
public void ConfigureDatabaseConnection(string connectionString)
|
||||
{
|
||||
SaveConnectionString(connectionString, string.Empty);
|
||||
var provider = DbConnectionExtensions.DetectProviderFromConnectionString(connectionString);
|
||||
var databaseProvider = provider.ToString();
|
||||
var providerName = "System.Data.SqlClient";
|
||||
if (databaseProvider.ToLower().Contains("mysql"))
|
||||
{
|
||||
providerName = "MySql.Data.MySqlClient";
|
||||
}
|
||||
SaveConnectionString(connectionString, providerName);
|
||||
Initialize(string.Empty);
|
||||
}
|
||||
|
||||
@@ -169,7 +176,7 @@ namespace Umbraco.Core
|
||||
SaveConnectionString(connectionString, providerName);
|
||||
Initialize(providerName);
|
||||
}
|
||||
|
||||
|
||||
public string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName)
|
||||
{
|
||||
providerName = "System.Data.SqlClient";
|
||||
@@ -465,6 +472,11 @@ namespace Umbraco.Core
|
||||
string message;
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
|
||||
// If MySQL, we're going to ensure that database calls are maintaining proper casing as to remove the necessity for checks
|
||||
// for case insensitive queries. In an ideal situation (which is what we're striving for), all calls would be case sensitive.
|
||||
|
||||
/*
|
||||
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
if (supportsCaseInsensitiveQueries == false)
|
||||
{
|
||||
@@ -477,8 +489,9 @@ namespace Umbraco.Core
|
||||
|
||||
return new Result { Message = message, Success = false, Percentage = "15" };
|
||||
}
|
||||
*/
|
||||
|
||||
message = GetResultMessageForMySql(supportsCaseInsensitiveQueries);
|
||||
message = GetResultMessageForMySql();
|
||||
|
||||
var schemaResult = ValidateDatabaseSchema();
|
||||
var installedVersion = schemaResult.DetermineInstalledVersion();
|
||||
@@ -529,9 +542,9 @@ namespace Umbraco.Core
|
||||
LogHelper.Info<DatabaseContext>("Database upgrade started");
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
//var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
|
||||
var message = GetResultMessageForMySql(supportsCaseInsensitiveQueries);
|
||||
var message = GetResultMessageForMySql();
|
||||
|
||||
var schemaResult = ValidateDatabaseSchema();
|
||||
var installedVersion = schemaResult.DetermineInstalledVersion();
|
||||
@@ -558,6 +571,23 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
private string GetResultMessageForMySql()
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
|
||||
{
|
||||
return "<p> </p><p>Congratulations, the database step ran successfully!</p>" +
|
||||
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
|
||||
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
|
||||
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/*
|
||||
private string GetResultMessageForMySql(bool? supportsCaseInsensitiveQueries)
|
||||
{
|
||||
if (supportsCaseInsensitiveQueries == null)
|
||||
@@ -581,7 +611,7 @@ namespace Umbraco.Core
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}*/
|
||||
|
||||
private Attempt<Result> CheckReadyForInstall()
|
||||
{
|
||||
|
||||
@@ -36,42 +36,22 @@ namespace Umbraco.Core.Dynamics
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
|
||||
{
|
||||
if (haystack == null) throw new ArgumentNullException("haystack");
|
||||
if (!string.IsNullOrEmpty(haystack) || needles.Any())
|
||||
{
|
||||
return needles.Any(haystack.Contains);
|
||||
}
|
||||
return false;
|
||||
return StringExtensions.ContainsAny(haystack, needles);
|
||||
}
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool ContainsAny(this string haystack, params string[] needles)
|
||||
{
|
||||
if (haystack == null) throw new ArgumentNullException("haystack");
|
||||
if (!string.IsNullOrEmpty(haystack) || needles.Length > 0)
|
||||
{
|
||||
return needles.Any(haystack.Contains);
|
||||
}
|
||||
return false;
|
||||
return StringExtensions.ContainsAny(haystack, needles);
|
||||
}
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool ContainsAny(this string haystack, StringComparison comparison, IEnumerable<string> needles)
|
||||
{
|
||||
if (haystack == null) throw new ArgumentNullException("haystack");
|
||||
if (!string.IsNullOrEmpty(haystack) || needles.Any())
|
||||
{
|
||||
return needles.Any(value => haystack.IndexOf(value, comparison) >= 0);
|
||||
}
|
||||
return false;
|
||||
return StringExtensions.ContainsAny(haystack, needles, comparison);
|
||||
}
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool ContainsAny(this string haystack, StringComparison comparison, params string[] needles)
|
||||
{
|
||||
if (haystack == null) throw new ArgumentNullException("haystack");
|
||||
if (!string.IsNullOrEmpty(haystack) || needles.Length > 0)
|
||||
{
|
||||
return needles.Any(value => haystack.IndexOf(value, comparison) >= 0);
|
||||
}
|
||||
return false;
|
||||
return StringExtensions.ContainsAny(haystack, needles, comparison);
|
||||
}
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool ContainsInsensitive(this string haystack, string needle)
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
internal class PropertyResult : IPublishedProperty, IHtmlString
|
||||
{
|
||||
private readonly IPublishedProperty _source;
|
||||
private readonly IPublishedProperty _source;
|
||||
private readonly string _alias;
|
||||
private readonly object _value;
|
||||
private readonly PropertyResultType _type;
|
||||
|
||||
internal PropertyResult(IPublishedProperty source, PropertyResultType type)
|
||||
internal PropertyResult(IPublishedProperty source, PropertyResultType type)
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException("source");
|
||||
|
||||
|
||||
@@ -15,43 +15,13 @@ namespace Umbraco.Core
|
||||
public static IEnumerable<IEnumerable<T>> InGroupsOf<T>(this IEnumerable<T> source, int groupSize)
|
||||
{
|
||||
if (source == null)
|
||||
throw new NullReferenceException("source");
|
||||
throw new ArgumentNullException("source");
|
||||
if (groupSize <= 0)
|
||||
throw new ArgumentException("Must be greater than zero.", "groupSize");
|
||||
|
||||
// enumerate the source only once!
|
||||
return new InGroupsEnumerator<T>(source, groupSize).Groups();
|
||||
}
|
||||
|
||||
// this class makes sure that the source is enumerated only ONCE
|
||||
// which means that when it is enumerated, the actual groups content
|
||||
// has to be evaluated at the same time, and stored in an array.
|
||||
private class InGroupsEnumerator<T>
|
||||
{
|
||||
private readonly IEnumerator<T> _source;
|
||||
private readonly int _count;
|
||||
private bool _mightHaveNext;
|
||||
|
||||
public InGroupsEnumerator(IEnumerable<T> source, int count)
|
||||
{
|
||||
_source = source.GetEnumerator();
|
||||
_count = count;
|
||||
_mightHaveNext = true;
|
||||
}
|
||||
|
||||
public IEnumerable<IEnumerable<T>> Groups()
|
||||
{
|
||||
while (_mightHaveNext && _source.MoveNext())
|
||||
yield return Group().ToArray(); // see note above
|
||||
}
|
||||
|
||||
private IEnumerable<T> Group()
|
||||
{
|
||||
var c = 0;
|
||||
do
|
||||
{
|
||||
yield return _source.Current;
|
||||
} while (++c < _count && _source.MoveNext());
|
||||
_mightHaveNext = c == _count;
|
||||
}
|
||||
return source
|
||||
.Select((x, i) => Tuple.Create(i / groupSize, x))
|
||||
.GroupBy(t => t.Item1, t => t.Item2);
|
||||
}
|
||||
|
||||
/// <summary>The distinct by.</summary>
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Events
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
protected T EventObject { get; private set; }
|
||||
protected T EventObject { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class MoveEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>
|
||||
{
|
||||
public MoveEventArgs(TEntity eventObject, bool canCancel, int parentId) : base(eventObject, canCancel)
|
||||
{
|
||||
ParentId = parentId;
|
||||
}
|
||||
public class MoveEventInfo<TEntity>
|
||||
{
|
||||
public MoveEventInfo(TEntity entity, string originalPath, int newParentId)
|
||||
{
|
||||
Entity = entity;
|
||||
OriginalPath = originalPath;
|
||||
NewParentId = newParentId;
|
||||
}
|
||||
|
||||
public MoveEventArgs(TEntity eventObject, int parentId) : base(eventObject)
|
||||
{
|
||||
ParentId = parentId;
|
||||
}
|
||||
public TEntity Entity { get; set; }
|
||||
public string OriginalPath { get; set; }
|
||||
public int NewParentId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The entity being moved
|
||||
/// </summary>
|
||||
public TEntity Entity
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
public class MoveEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting a collection of MoveEventInfo objects
|
||||
/// </summary>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="moveInfo">
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(bool canCancel, params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity), canCancel)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
throw new ArgumentException("moveInfo argument must contain at least one item");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the Id of the objects new parent.
|
||||
/// </summary>
|
||||
public int ParentId { get; private set; }
|
||||
}
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a collection of MoveEventInfo objects
|
||||
/// </summary>
|
||||
/// <param name="moveInfo">
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity))
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
throw new ArgumentException("moveInfo argument must contain at least one item");
|
||||
}
|
||||
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
|
||||
public MoveEventArgs(TEntity eventObject, bool canCancel, int parentId)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
ParentId = parentId;
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload that specifies the MoveEventInfo object")]
|
||||
public MoveEventArgs(TEntity eventObject, int parentId)
|
||||
: base(eventObject)
|
||||
{
|
||||
ParentId = parentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all MoveEventInfo objects used to create the object
|
||||
/// </summary>
|
||||
public IEnumerable<MoveEventInfo<TEntity>> MoveInfoCollection { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The entity being moved
|
||||
/// </summary>
|
||||
[Obsolete("Retrieve the entity object from the MoveInfoCollection property instead")]
|
||||
public TEntity Entity
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Id of the object's new parent
|
||||
/// </summary>
|
||||
[Obsolete("Retrieve the ParentId from the MoveInfoCollection property instead")]
|
||||
public int ParentId { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
|
||||
//NOTE: Could definitely have done with a better name
|
||||
//TODO: Could definitely have done with a better name
|
||||
public class Result
|
||||
{
|
||||
public Status Status { get; set; }
|
||||
|
||||
@@ -232,6 +232,7 @@ namespace Umbraco.Core.Models
|
||||
/// <remarks>
|
||||
/// This Property is kept internal until localization is introduced.
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
internal string NodeName
|
||||
{
|
||||
get { return _nodeName; }
|
||||
@@ -248,6 +249,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Used internally to track if permissions have been changed during the saving process for this entity
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal bool PermissionsChanged
|
||||
{
|
||||
get { return _permissionsChanged; }
|
||||
@@ -314,6 +316,7 @@ namespace Umbraco.Core.Models
|
||||
PublishedState = state;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
internal PublishedState PublishedState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -333,26 +336,6 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a clone of the current entity
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IContent Clone()
|
||||
{
|
||||
var clone = (Content)this.MemberwiseClone();
|
||||
clone.Key = Guid.Empty;
|
||||
clone.Version = Guid.NewGuid();
|
||||
clone.ResetIdentity();
|
||||
|
||||
foreach (var property in clone.Properties)
|
||||
{
|
||||
property.ResetIdentity();
|
||||
property.Version = clone.Version;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a specific property on the current <see cref="IContent"/> entity is dirty.
|
||||
/// </summary>
|
||||
@@ -432,5 +415,47 @@ namespace Umbraco.Core.Models
|
||||
base.UpdatingEntity();
|
||||
Version = Guid.NewGuid();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity and it's property identities reset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use DeepCloneWithResetIdentities instead")]
|
||||
public IContent Clone()
|
||||
{
|
||||
return DeepCloneWithResetIdentities();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity and it's property identities reset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IContent DeepCloneWithResetIdentities()
|
||||
{
|
||||
var clone = (Content)DeepClone();
|
||||
clone.Key = Guid.Empty;
|
||||
clone.Version = Guid.NewGuid();
|
||||
clone.ResetIdentity();
|
||||
|
||||
foreach (var property in clone.Properties)
|
||||
{
|
||||
property.ResetIdentity();
|
||||
property.Version = clone.Version;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Content)base.DeepClone();
|
||||
|
||||
//need to manually clone this since it's not settable
|
||||
clone._contentType = (IContentType)ContentType.DeepClone();
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Represents an abstract class for base Content properties and methods
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
[DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")]
|
||||
public abstract class ContentBase : Entity, IContentBase
|
||||
{
|
||||
protected IContentTypeComposition ContentTypeBase;
|
||||
|
||||
private Lazy<int> _parentId;
|
||||
private string _name;//NOTE Once localization is introduced this will be the localized Name of the Content/Media.
|
||||
private int _sortOrder;
|
||||
@@ -257,6 +260,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, object> _additionalData;
|
||||
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
@@ -445,6 +449,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Returns a collection of the result of the last validation process, this collection contains all invalid properties.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal IEnumerable<Property> LastInvalidProperties
|
||||
{
|
||||
get { return _lastInvalidProperties; }
|
||||
@@ -466,5 +471,6 @@ namespace Umbraco.Core.Models
|
||||
prop.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Used content repository in order to add an entity to the persisted collection to be saved
|
||||
/// in a single transaction during saving an entity
|
||||
/// </summary>
|
||||
internal class ContentPreviewEntity<TContent> : ContentXmlEntity<TContent>
|
||||
where TContent : IContentBase
|
||||
{
|
||||
public ContentPreviewEntity(bool previewExists, TContent content, Func<TContent, XElement> xml)
|
||||
: base(previewExists, content, xml)
|
||||
{
|
||||
Version = content.Version;
|
||||
}
|
||||
|
||||
public Guid Version { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -120,38 +120,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a clone of the current entity
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IContentType Clone(string alias)
|
||||
{
|
||||
var clone = (ContentType)this.MemberwiseClone();
|
||||
clone.Alias = alias;
|
||||
clone.Key = Guid.Empty;
|
||||
var propertyGroups = this.PropertyGroups.Select(x => x.Clone()).ToList();
|
||||
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
|
||||
clone.PropertyTypes = this.PropertyTypeCollection.Select(x => x.Clone()).ToList();
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
foreach (var propertyGroup in clone.PropertyGroups)
|
||||
{
|
||||
propertyGroup.ResetIdentity();
|
||||
foreach (var propertyType in propertyGroup.PropertyTypes)
|
||||
{
|
||||
propertyType.ResetIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var propertyType in clone.PropertyTypes.Where(x => x.HasIdentity))
|
||||
{
|
||||
propertyType.ResetIdentity();
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being saved
|
||||
@@ -173,5 +141,56 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
base.UpdatingEntity();
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentType)base.DeepClone();
|
||||
var propertyGroups = PropertyGroups.Select(x => (PropertyGroup)x.DeepClone()).ToList();
|
||||
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
|
||||
//set the property types that are not part of a group
|
||||
clone.PropertyTypes = PropertyTypeCollection
|
||||
.Where(x => x.PropertyGroupId == null)
|
||||
.Select(x => (PropertyType)x.DeepClone()).ToList();
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use DeepCloneWithResetIdentities instead")]
|
||||
public IContentType Clone(string alias)
|
||||
{
|
||||
return DeepCloneWithResetIdentities(alias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IContentType DeepCloneWithResetIdentities(string alias)
|
||||
{
|
||||
var clone = (ContentType)DeepClone();
|
||||
clone.Alias = alias;
|
||||
clone.Key = Guid.Empty;
|
||||
foreach (var propertyGroup in clone.PropertyGroups)
|
||||
{
|
||||
propertyGroup.ResetIdentity();
|
||||
propertyGroup.ResetDirtyProperties(false);
|
||||
}
|
||||
foreach (var propertyType in clone.PropertyTypes)
|
||||
{
|
||||
propertyType.ResetIdentity();
|
||||
propertyType.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -173,7 +174,8 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_alias = value.ToSafeAlias();
|
||||
//_alias = value.ToSafeAlias();
|
||||
_alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase);
|
||||
return _alias;
|
||||
}, _alias, AliasSelector);
|
||||
}
|
||||
@@ -319,7 +321,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, object> _additionalData;
|
||||
private IDictionary<string, object> _additionalData;
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public abstract class ContentTypeCompositionBase : ContentTypeBase, IContentTypeComposition
|
||||
{
|
||||
private readonly List<IContentTypeComposition> _contentTypeComposition = new List<IContentTypeComposition>();
|
||||
private List<IContentTypeComposition> _contentTypeComposition = new List<IContentTypeComposition>();
|
||||
internal List<int> RemovedContentTypeKeyTracker = new List<int>();
|
||||
|
||||
protected ContentTypeCompositionBase(int parentId) : base(parentId)
|
||||
@@ -217,5 +217,17 @@ namespace Umbraco.Core.Models
|
||||
.Select(x => x.Id)
|
||||
.Union(ContentTypeComposition.SelectMany(x => x.CompositionIds()));
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentTypeCompositionBase)base.DeepClone();
|
||||
|
||||
//need to manually assign since this is an internal field and will not be automatically mapped
|
||||
clone.RemovedContentTypeKeyTracker = new List<int>();
|
||||
clone._contentTypeComposition = ContentTypeComposition.Select(x => (IContentTypeComposition)x.DeepClone()).ToList();
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Represents a POCO for setting sort order on a ContentType reference
|
||||
/// </summary>
|
||||
public class ContentTypeSort : IValueObject
|
||||
public class ContentTypeSort : IValueObject, IDeepCloneable
|
||||
{
|
||||
public ContentTypeSort()
|
||||
{
|
||||
@@ -33,5 +33,36 @@ namespace Umbraco.Core.Models
|
||||
/// Gets or sets the Alias of the ContentType
|
||||
/// </summary>
|
||||
public string Alias { get; set; }
|
||||
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = (ContentTypeSort)MemberwiseClone();
|
||||
var id = Id.Value;
|
||||
clone.Id = new Lazy<int>(() => id);
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected bool Equals(ContentTypeSort other)
|
||||
{
|
||||
return Id.Value.Equals(other.Id.Value) && string.Equals(Alias, other.Alias);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((ContentTypeSort) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (Id.GetHashCode()*397) ^ Alias.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Used in content/media/member repositories in order to add this type of entity to the persisted collection to be saved
|
||||
/// in a single transaction during saving an entity
|
||||
/// </summary>
|
||||
internal class ContentXmlEntity<TContent> : IAggregateRoot
|
||||
where TContent : IContentBase
|
||||
{
|
||||
private readonly bool _entityExists;
|
||||
private readonly Func<TContent, XElement> _xml;
|
||||
|
||||
public ContentXmlEntity(bool entityExists, TContent content, Func<TContent, XElement> xml)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
_entityExists = entityExists;
|
||||
_xml = xml;
|
||||
Content = content;
|
||||
}
|
||||
|
||||
public ContentXmlEntity(TContent content)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
Content = content;
|
||||
}
|
||||
|
||||
public XElement Xml
|
||||
{
|
||||
get { return _xml(Content); }
|
||||
}
|
||||
public TContent Content { get; private set; }
|
||||
|
||||
public int Id
|
||||
{
|
||||
get { return Content.Id; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public Guid Key { get; set; }
|
||||
public DateTime CreateDate { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
|
||||
public bool HasIdentity
|
||||
{
|
||||
get { return _entityExists; }
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = (ContentXmlEntity<TContent>)MemberwiseClone();
|
||||
//Automatically deep clone ref properties that are IDeepCloneable
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public static class DeepCloneHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to deep clone any reference properties on the object (should be done after a MemberwiseClone for which the outcome is 'output')
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="output"></param>
|
||||
/// <returns></returns>
|
||||
public static void DeepCloneRefProperties(IDeepCloneable input, IDeepCloneable output)
|
||||
{
|
||||
var inputType = input.GetType();
|
||||
var outputType = output.GetType();
|
||||
|
||||
if (inputType != outputType)
|
||||
{
|
||||
throw new InvalidOperationException("Both the input and output types must be the same");
|
||||
}
|
||||
|
||||
var refProperties = inputType.GetProperties()
|
||||
.Where(x =>
|
||||
//reference type but not string
|
||||
x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|
||||
//settable
|
||||
&& x.CanWrite
|
||||
//non-indexed
|
||||
&& x.GetIndexParameters().Any() == false);
|
||||
|
||||
foreach (var propertyInfo in refProperties)
|
||||
{
|
||||
if (TypeHelper.IsTypeAssignableFrom<IDeepCloneable>(propertyInfo.PropertyType))
|
||||
{
|
||||
//this ref property is also deep cloneable so clone it
|
||||
var result = (IDeepCloneable)propertyInfo.GetValue(input, null);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
//set the cloned value to the property
|
||||
propertyInfo.SetValue(output, result.DeepClone(), null);
|
||||
}
|
||||
}
|
||||
else if (TypeHelper.IsTypeAssignableFrom<IEnumerable>(propertyInfo.PropertyType)
|
||||
&& TypeHelper.IsTypeAssignableFrom<string>(propertyInfo.PropertyType) == false)
|
||||
{
|
||||
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
|
||||
{
|
||||
//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);
|
||||
if (enumerable == null) continue;
|
||||
|
||||
var isUsableType = true;
|
||||
|
||||
//now clone each item
|
||||
foreach (var o in enumerable)
|
||||
{
|
||||
//first check if the item is deep cloneable and copy that way
|
||||
var dc = o as IDeepCloneable;
|
||||
if (dc != null)
|
||||
{
|
||||
newList.Add(dc.DeepClone());
|
||||
}
|
||||
else if (o is string || o.GetType().IsValueType)
|
||||
{
|
||||
//check if the item is a value type or a string, then we can just use it
|
||||
newList.Add(o);
|
||||
}
|
||||
else
|
||||
{
|
||||
//this will occur if the item is not a string or value type or IDeepCloneable, in this case we cannot
|
||||
// clone each element, we'll need to skip this property, people will have to manually clone this list
|
||||
isUsableType = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if this was not usable, skip this property
|
||||
if (isUsableType == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (propertyInfo.PropertyType.IsArray)
|
||||
{
|
||||
//need to convert to array
|
||||
var arr = (object[])Activator.CreateInstance(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);
|
||||
}
|
||||
else
|
||||
{
|
||||
//set the cloned collection
|
||||
propertyInfo.SetValue(output, newList, null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
@@ -96,5 +97,6 @@ namespace Umbraco.Core.Models
|
||||
if(ParentId == Guid.Empty)
|
||||
_parentId = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -65,5 +65,6 @@ namespace Umbraco.Core.Models
|
||||
}, _value, ValueSelector);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
@@ -93,7 +96,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// /// Gets or sets the WasCancelled flag, which is used to track
|
||||
/// Gets or sets the WasCancelled flag, which is used to track
|
||||
/// whether some action against an entity was cancelled through some event.
|
||||
/// This only exists so we have a way to check if an event was cancelled through
|
||||
/// the new api, which also needs to take effect in the legacy api.
|
||||
@@ -155,6 +158,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// <summary>
|
||||
/// Indicates whether the current entity has an identity, eg. Id.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public virtual bool HasIdentity
|
||||
{
|
||||
get
|
||||
@@ -226,5 +230,62 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
_hash = !HasIdentity ? new int?(base.GetHashCode()) : new int?(Id.GetHashCode() * 397 ^ GetType().GetHashCode());
|
||||
return _hash.Value;
|
||||
}
|
||||
|
||||
public virtual object DeepClone()
|
||||
{
|
||||
//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 clone = (Entity)MemberwiseClone();
|
||||
//Automatically deep clone ref properties that are IDeepCloneable
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
|
||||
//Using data contract serializer - has issues
|
||||
|
||||
//var s = Serialize(this);
|
||||
//var d = Deserialize(s, this.GetType());
|
||||
//return d;
|
||||
|
||||
//Using binary serializer - has issues
|
||||
|
||||
//using (var memoryStream = new MemoryStream(10))
|
||||
//{
|
||||
//IFormatter formatter = new BinaryFormatter();
|
||||
//formatter.Serialize(memoryStream, this);
|
||||
//memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
//return formatter.Deserialize(memoryStream);
|
||||
//}
|
||||
}
|
||||
|
||||
// serialize/deserialize with data contracts:
|
||||
|
||||
//public static string Serialize(object obj)
|
||||
//{
|
||||
// using (var memoryStream = new MemoryStream())
|
||||
// using (var reader = new StreamReader(memoryStream))
|
||||
// {
|
||||
// var serializer = new DataContractSerializer(obj.GetType());
|
||||
// serializer.WriteObject(memoryStream, obj);
|
||||
// memoryStream.Position = 0;
|
||||
// return reader.ReadToEnd();
|
||||
// }
|
||||
//}
|
||||
|
||||
//public static object Deserialize(string xml, Type toType)
|
||||
//{
|
||||
// using (Stream stream = new MemoryStream())
|
||||
// {
|
||||
// using (var writer = new StreamWriter(stream, Encoding.UTF8))
|
||||
// {
|
||||
// writer.Write(xml);
|
||||
// //byte[] data = Encoding.UTF8.GetBytes(xml);
|
||||
// //stream.Write(data, 0, data.Length);
|
||||
// stream.Position = 0;
|
||||
// var deserializer = new DataContractSerializer(toType);
|
||||
// return deserializer.ReadObject(stream);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// </summary>
|
||||
/// <remarks>The current database schema doesn't provide a modified date
|
||||
/// for all entities, so this will have to be changed at a later stage.</remarks>
|
||||
public interface IEntity
|
||||
public interface IEntity : IDeepCloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// The Id of the entity
|
||||
|
||||
@@ -3,18 +3,21 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for use to implement IRememberBeingDirty/ICanBeDirty
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public abstract class TracksChangesEntityBase : IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks the properties that have changed
|
||||
/// </summary>
|
||||
private readonly IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
|
||||
private IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Tracks the properties that we're changed before the last commit (or last call to ResetDirtyProperties)
|
||||
@@ -83,7 +86,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// </summary>
|
||||
public void ForgetPreviouslyDirtyProperties()
|
||||
{
|
||||
_lastPropertyChangedInfo.Clear();
|
||||
//NOTE: We cannot .Clear() because when we memberwise clone this will be the SAME
|
||||
// instance as the one on the clone, so we need to create a new instance.
|
||||
_lastPropertyChangedInfo = new Dictionary<string, bool>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -116,7 +121,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
_lastPropertyChangedInfo = _propertyChangedInfo.ToDictionary(v => v.Key, v => v.Value);
|
||||
}
|
||||
|
||||
_propertyChangedInfo.Clear();
|
||||
//NOTE: We cannot .Clear() because when we memberwise clone this will be the SAME
|
||||
// instance as the one on the clone, so we need to create a new instance.
|
||||
_propertyChangedInfo = new Dictionary<string, bool>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,16 +6,6 @@ using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal sealed class Folder : Entity
|
||||
{
|
||||
public Folder(string folderPath)
|
||||
{
|
||||
Path = folderPath;
|
||||
}
|
||||
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an abstract file which provides basic functionality for a File with an Alias and Name
|
||||
/// </summary>
|
||||
@@ -114,5 +104,18 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <returns>True if file is valid, otherwise false</returns>
|
||||
public abstract bool IsValid();
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (File)base.DeepClone();
|
||||
|
||||
//need to manually assign since they are readonly properties
|
||||
clone._alias = Alias;
|
||||
clone._name = Name;
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal sealed class Folder : Entity
|
||||
{
|
||||
public Folder(string folderPath)
|
||||
{
|
||||
Path = folderPath;
|
||||
}
|
||||
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -72,5 +72,11 @@ namespace Umbraco.Core.Models
|
||||
/// Changes the Published state of the content object
|
||||
/// </summary>
|
||||
void ChangePublishedState(PublishedState state);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IContent DeepCloneWithResetIdentities();
|
||||
}
|
||||
}
|
||||
@@ -29,5 +29,12 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="template"><see cref="ITemplate"/> to remove</param>
|
||||
/// <returns>True if template was removed, otherwise False</returns>
|
||||
bool RemoveTemplate(ITemplate template);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
/// </summary>
|
||||
/// <param name="newAlias"></param>
|
||||
/// <returns></returns>
|
||||
IContentType DeepCloneWithResetIdentities(string newAlias);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IDeepCloneable
|
||||
{
|
||||
object DeepClone();
|
||||
}
|
||||
}
|
||||
@@ -109,9 +109,9 @@ namespace Umbraco.Core.Models
|
||||
private string _scriptAssembly;
|
||||
private string _scriptPath;
|
||||
private string _xslt;
|
||||
private readonly MacroPropertyCollection _properties;
|
||||
private readonly List<string> _addedProperties;
|
||||
private readonly List<string> _removedProperties;
|
||||
private MacroPropertyCollection _properties;
|
||||
private List<string> _addedProperties;
|
||||
private List<string> _removedProperties;
|
||||
|
||||
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.Alias);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.Name);
|
||||
@@ -397,7 +397,19 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
get { return _properties; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Macro)base.DeepClone();
|
||||
|
||||
clone._addedProperties = new List<string>();
|
||||
clone._removedProperties = new List<string>();
|
||||
clone._properties = new MacroPropertyCollection();
|
||||
clone._properties.CollectionChanged += clone.PropertiesChanged;
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class Member : ContentBase, IMember
|
||||
{
|
||||
private readonly IMemberType _contentType;
|
||||
private IMemberType _contentType;
|
||||
private readonly string _contentTypeAlias;
|
||||
private string _username;
|
||||
private string _email;
|
||||
@@ -153,7 +153,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Gets or sets the raw password value
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
[IgnoreDataMember]
|
||||
public string RawPasswordValue
|
||||
{
|
||||
get { return _rawPasswordValue; }
|
||||
@@ -184,7 +184,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberPasswordRetrievalQuestion
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public string PasswordQuestion
|
||||
{
|
||||
get
|
||||
@@ -244,7 +244,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberComments
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public string Comments
|
||||
{
|
||||
get
|
||||
@@ -273,7 +273,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberApproved
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public bool IsApproved
|
||||
{
|
||||
get
|
||||
@@ -308,7 +308,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberLockedOut
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public bool IsLockedOut
|
||||
{
|
||||
get
|
||||
@@ -341,7 +341,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberLastLogin
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public DateTime LastLoginDate
|
||||
{
|
||||
get
|
||||
@@ -374,7 +374,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberLastPasswordChangeDate
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public DateTime LastPasswordChangeDate
|
||||
{
|
||||
get
|
||||
@@ -407,7 +407,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberLastLockoutDate
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public DateTime LastLockoutDate
|
||||
{
|
||||
get
|
||||
@@ -441,7 +441,7 @@ namespace Umbraco.Core.Models
|
||||
/// Alias: umbracoMemberFailedPasswordAttempts
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DataMember]
|
||||
public int FailedPasswordAttempts
|
||||
{
|
||||
get
|
||||
@@ -563,11 +563,17 @@ namespace Umbraco.Core.Models
|
||||
/* Internal experiment - only used for mapping queries.
|
||||
* Adding these to have first level properties instead of the Properties collection.
|
||||
*/
|
||||
[IgnoreDataMember]
|
||||
internal string LongStringPropertyValue { get; set; }
|
||||
[IgnoreDataMember]
|
||||
internal string ShortStringPropertyValue { get; set; }
|
||||
[IgnoreDataMember]
|
||||
internal int IntegerropertyValue { get; set; }
|
||||
[IgnoreDataMember]
|
||||
internal bool BoolPropertyValue { get; set; }
|
||||
[IgnoreDataMember]
|
||||
internal DateTime DateTimePropertyValue { get; set; }
|
||||
[IgnoreDataMember]
|
||||
internal string PropertyTypeAlias { get; set; }
|
||||
|
||||
private Attempt<T> WarnIfPropertyTypeNotFoundOnGet<T>(string propertyAlias, string propertyName, T defaultVal)
|
||||
@@ -637,5 +643,17 @@ namespace Umbraco.Core.Models
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Member)base.DeepClone();
|
||||
|
||||
//need to manually clone this since it's not settable
|
||||
clone._contentType = (IMemberType)ContentType.DeepClone();
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class User : TracksChangesEntityBase, IUser
|
||||
public class User : Entity, IUser
|
||||
{
|
||||
public User(IUserType userType)
|
||||
{
|
||||
@@ -57,13 +57,11 @@ namespace Umbraco.Core.Models.Membership
|
||||
}
|
||||
|
||||
private IUserType _userType;
|
||||
private bool _hasIdentity;
|
||||
private int _id;
|
||||
private string _name;
|
||||
private Type _userTypeKey;
|
||||
private readonly List<string> _addedSections;
|
||||
private readonly List<string> _removedSections;
|
||||
private readonly ObservableCollection<string> _sectionCollection;
|
||||
private List<string> _addedSections;
|
||||
private List<string> _removedSections;
|
||||
private ObservableCollection<string> _sectionCollection;
|
||||
private int _sessionTimeout;
|
||||
private int _startContentId;
|
||||
private int _startMediaId;
|
||||
@@ -81,7 +79,6 @@ namespace Umbraco.Core.Models.Membership
|
||||
private static readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartContentId);
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
|
||||
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
|
||||
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<User, object>(x => x.Id);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<User, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
@@ -93,52 +90,8 @@ namespace Umbraco.Core.Models.Membership
|
||||
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
|
||||
private static readonly PropertyInfo DefaultPermissionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.DefaultPermissions);
|
||||
private static readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
|
||||
private static readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.HasIdentity);
|
||||
private static readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo<User, IUserType>(x => x.UserType);
|
||||
|
||||
#region Implementation of IEntity
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool HasIdentity
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hasIdentity;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_hasIdentity = value;
|
||||
return _hasIdentity;
|
||||
}, _hasIdentity, HasIdentitySelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_id = value;
|
||||
HasIdentity = true; //set the has Identity
|
||||
return _id;
|
||||
}, _id, IdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
//this doesn't get used
|
||||
[IgnoreDataMember]
|
||||
public Guid Key { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Implementation of IMembershipUser
|
||||
|
||||
[IgnoreDataMember]
|
||||
@@ -256,11 +209,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
[IgnoreDataMember]
|
||||
public string RawPasswordAnswerValue { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string Comments { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime CreateDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public string Comments { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
@@ -295,7 +244,10 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
public void RemoveAllowedSection(string sectionAlias)
|
||||
{
|
||||
_sectionCollection.Remove(sectionAlias);
|
||||
if (_sectionCollection.Contains(sectionAlias))
|
||||
{
|
||||
_sectionCollection.Remove(sectionAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAllowedSection(string sectionAlias)
|
||||
@@ -474,24 +426,41 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
var item = e.NewItems.Cast<string>().First();
|
||||
|
||||
//add to the added sections
|
||||
_addedSections.Add(e.NewItems.Cast<string>().First());
|
||||
if (_addedSections.Contains(item) == false)
|
||||
{
|
||||
_addedSections.Add(item);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
var item = e.OldItems.Cast<string>().First();
|
||||
|
||||
if (_removedSections.Contains(item) == false)
|
||||
{
|
||||
_removedSections.Add(item);
|
||||
}
|
||||
|
||||
//add to the added sections
|
||||
_removedSections.Add(e.OldItems.Cast<string>().First());
|
||||
}
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (User)base.DeepClone();
|
||||
|
||||
//need to create new collections otherwise they'll get copied by ref
|
||||
clone._addedSections = new List<string>();
|
||||
clone._removedSections = new List<string>();
|
||||
clone._sectionCollection = new ObservableCollection<string>(_sectionCollection.ToList());
|
||||
//re-create the event handler
|
||||
clone._sectionCollection.CollectionChanged += clone.SectionCollectionChanged;
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal class used to wrap the user in a profile
|
||||
/// </summary>
|
||||
@@ -515,6 +484,24 @@ namespace Umbraco.Core.Models.Membership
|
||||
get { return _user.Name; }
|
||||
set { _user.Name = value; }
|
||||
}
|
||||
|
||||
protected bool Equals(UserProfile other)
|
||||
{
|
||||
return _user.Equals(other._user);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((UserProfile) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _user.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal class Notification
|
||||
public class Notification
|
||||
{
|
||||
public Notification(int entityId, int userId, string action, Guid entityType)
|
||||
{
|
||||
|
||||
@@ -5,10 +5,17 @@
|
||||
/// </summary>
|
||||
public class PreValue
|
||||
{
|
||||
public PreValue(int id, string value, int sortOrder)
|
||||
{
|
||||
Id = id;
|
||||
Value = value;
|
||||
SortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public PreValue(int id, string value)
|
||||
{
|
||||
Value = value;
|
||||
Id = id;
|
||||
Id = id;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public PreValue(string value)
|
||||
@@ -19,11 +26,16 @@
|
||||
/// <summary>
|
||||
/// The value stored for the pre-value field
|
||||
/// </summary>
|
||||
public string Value { get; private set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The database id for the pre-value field value
|
||||
/// </summary>
|
||||
public int Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The sort order stored for the pre-value field value
|
||||
/// </summary>
|
||||
public int SortOrder { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class Property : Entity
|
||||
{
|
||||
private readonly PropertyType _propertyType;
|
||||
private PropertyType _propertyType;
|
||||
private Guid _version;
|
||||
private object _value;
|
||||
private readonly PropertyTags _tagSupport = new PropertyTags();
|
||||
@@ -156,5 +156,16 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
return _propertyType.IsPropertyValueValid(value);
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Property)base.DeepClone();
|
||||
|
||||
//need to manually assign since this is a readonly property
|
||||
clone._propertyType = (PropertyType)PropertyType.DeepClone();
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -13,7 +14,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class PropertyCollection : KeyedCollection<string, Property>, INotifyCollectionChanged
|
||||
public class PropertyCollection : KeyedCollection<string, Property>, INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
internal Action OnAdd;
|
||||
@@ -195,5 +196,19 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a deep clone of this property collection
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public object DeepClone()
|
||||
{
|
||||
var newList = new PropertyCollection();
|
||||
foreach (var p in this)
|
||||
{
|
||||
newList.Add((Property)p.DeepClone());
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,38 +17,9 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml of the property and its value</returns>
|
||||
public static XElement ToXml(this Property property)
|
||||
{
|
||||
return property.ToXml(property.PropertyType, ApplicationContext.Current.Services.DataTypeService);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="Property"/> object
|
||||
/// </summary>
|
||||
/// <param name="property"><see cref="Property"/> to generate xml for</param>
|
||||
/// <param name="propertyType"></param>
|
||||
/// <param name="dataTypeService"></param>
|
||||
/// <returns>Xml of the property and its value</returns>
|
||||
internal static XElement ToXml(this Property property, PropertyType propertyType, IDataTypeService dataTypeService)
|
||||
{
|
||||
var nodeName = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
|
||||
|
||||
var xElement = new XElement(nodeName);
|
||||
|
||||
//Add the property alias to the legacy schema
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema)
|
||||
{
|
||||
var a = new XAttribute("alias", property.Alias.ToSafeAlias());
|
||||
xElement.Add(a);
|
||||
}
|
||||
|
||||
//Get the property editor for thsi property and let it convert it to the xml structure
|
||||
var propertyEditor = PropertyEditorResolver.Current.GetByAlias(property.PropertyType.PropertyEditorAlias);
|
||||
if (propertyEditor != null)
|
||||
{
|
||||
var xmlValue = propertyEditor.ValueEditor.ConvertDbToXml(property, propertyType, dataTypeService);
|
||||
xElement.Add(xmlValue);
|
||||
}
|
||||
|
||||
return xElement;
|
||||
var xmlSerializer = new EntityXmlSerializer();
|
||||
return xmlSerializer.Serialize(ApplicationContext.Current.Services.DataTypeService, property);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -109,23 +109,6 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
internal PropertyGroup Clone()
|
||||
{
|
||||
var clone = (PropertyGroup) this.MemberwiseClone();
|
||||
var collection = new PropertyTypeCollection();
|
||||
foreach (var propertyType in this.PropertyTypes)
|
||||
{
|
||||
var property = propertyType.Clone();
|
||||
property.ResetIdentity();
|
||||
property.ResetDirtyProperties(false);
|
||||
collection.Add(property);
|
||||
}
|
||||
clone.PropertyTypes = collection;
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ParentId from the lazy integer id
|
||||
/// </summary>
|
||||
@@ -159,5 +142,6 @@ namespace Umbraco.Core.Models
|
||||
//Calculate the hash code for the product.
|
||||
return hashName ^ hashId;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -13,9 +14,10 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract]
|
||||
public class PropertyGroupCollection : KeyedCollection<string, PropertyGroup>, INotifyCollectionChanged
|
||||
public class PropertyGroupCollection : KeyedCollection<string, PropertyGroup>, INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
|
||||
internal Action OnAdd;
|
||||
|
||||
internal PropertyGroupCollection()
|
||||
@@ -131,5 +133,15 @@ namespace Umbraco.Core.Models
|
||||
CollectionChanged(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var newGroup = new PropertyGroupCollection();
|
||||
foreach (var p in this)
|
||||
{
|
||||
newGroup.Add((PropertyGroup)p.DeepClone());
|
||||
}
|
||||
return newGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -96,7 +97,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_alias = value;
|
||||
_alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase);
|
||||
return _alias;
|
||||
}, _alias, AliasSelector);
|
||||
}
|
||||
@@ -405,7 +406,9 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//TODO: We must ensure that the property value can actually be saved based on the specified database type
|
||||
|
||||
//TODO Add PropertyEditor validation when its relevant to introduce
|
||||
/*if (value is IEditorModel && DataTypeControlId != Guid.Empty)
|
||||
{
|
||||
@@ -419,14 +422,6 @@ namespace Umbraco.Core.Models
|
||||
return true;
|
||||
}
|
||||
|
||||
internal PropertyType Clone()
|
||||
{
|
||||
var clone = (PropertyType) MemberwiseClone();
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public bool Equals(PropertyType other)
|
||||
{
|
||||
//Check whether the compared object is null.
|
||||
@@ -450,5 +445,20 @@ namespace Umbraco.Core.Models
|
||||
//Calculate the hash code for the product.
|
||||
return hashName ^ hashAlias;
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (PropertyType)base.DeepClone();
|
||||
|
||||
//need to manually assign the Lazy value as it will not be automatically mapped
|
||||
if (PropertyGroupId != null)
|
||||
{
|
||||
clone._propertyGroupId = new Lazy<int>(() => PropertyGroupId.Value);
|
||||
}
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -13,9 +14,12 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract]
|
||||
public class PropertyTypeCollection : KeyedCollection<string, PropertyType>, INotifyCollectionChanged
|
||||
public class PropertyTypeCollection : KeyedCollection<string, PropertyType>, INotifyCollectionChanged, IDeepCloneable
|
||||
{
|
||||
[IgnoreDataMember]
|
||||
private readonly ReaderWriterLockSlim _addLocker = new ReaderWriterLockSlim();
|
||||
|
||||
[IgnoreDataMember]
|
||||
internal Action OnAdd;
|
||||
|
||||
internal PropertyTypeCollection()
|
||||
@@ -131,5 +135,15 @@ namespace Umbraco.Core.Models
|
||||
CollectionChanged(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var newGroup = new PropertyTypeCollection();
|
||||
foreach (var p in this)
|
||||
{
|
||||
newGroup.Add((PropertyType)p.DeepClone());
|
||||
}
|
||||
return newGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,6 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
@@ -18,6 +16,32 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// if the property type changes, then a new class needs to be created.</remarks>
|
||||
public class PublishedPropertyType
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
// clone
|
||||
private PublishedPropertyType(PublishedPropertyType orig)
|
||||
{
|
||||
ContentType = orig.ContentType;
|
||||
PropertyTypeAlias = orig.PropertyTypeAlias;
|
||||
DataTypeId = orig.DataTypeId;
|
||||
PropertyEditorAlias = orig.PropertyEditorAlias;
|
||||
_converter = orig._converter;
|
||||
_sourceCacheLevel = orig._sourceCacheLevel;
|
||||
_objectCacheLevel = orig._objectCacheLevel;
|
||||
_xpathCacheLevel = orig._xpathCacheLevel;
|
||||
_clrType = orig._clrType;
|
||||
|
||||
// do NOT copy the reduced cache levels
|
||||
// as we should NOT clone a nested / detached type
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a new instance of the <see cref="PublishedPropertyType"/> class within a <see cref="PublishedContentType"/>,
|
||||
/// with a <see cref="PropertyType"/>.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The published content type.</param>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <remarks>The new published property type belongs to the published content type and corresponds to the property type.</remarks>
|
||||
public PublishedPropertyType(PublishedContentType contentType, PropertyType propertyType)
|
||||
{
|
||||
// PropertyEditor [1:n] DataTypeDefinition [1:n] PropertyType
|
||||
@@ -31,10 +55,68 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
InitializeConverters();
|
||||
}
|
||||
|
||||
// for unit tests
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedPropertyType"/> class with an existing <see cref="PublishedPropertyType"/>
|
||||
/// and a new property type alias.
|
||||
/// </summary>
|
||||
/// <param name="propertyTypeAlias">The new property type alias.</param>
|
||||
/// <param name="propertyType">The existing published property type.</param>
|
||||
/// <remarks>
|
||||
/// <para>The new published property type does not belong to a published content type.</para>
|
||||
/// <para>It is a copy of the initial published property type, with a different alias.</para>
|
||||
/// </remarks>
|
||||
internal PublishedPropertyType(string propertyTypeAlias, PublishedPropertyType propertyType)
|
||||
: this(propertyTypeAlias, propertyType.DataTypeId, propertyType.PropertyEditorAlias)
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedPropertyType"/> class with a property type alias and a property editor alias.
|
||||
/// </summary>
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <param name="propertyEditorAlias">The property editor alias.</param>
|
||||
/// <remarks>
|
||||
/// <para>The new published property type does not belong to a published content type.</para>
|
||||
/// <para>It is based upon the property editor, but has no datatype definition. This will work as long
|
||||
/// as the datatype definition is not required to process (eg to convert) the property values. For
|
||||
/// example, this may not work if the related IPropertyValueConverter requires the datatype definition
|
||||
/// to make decisions, fetch prevalues, etc.</para>
|
||||
/// <para>The value of <paramref name="propertyEditorAlias"/> is assumed to be valid.</para>
|
||||
/// </remarks>
|
||||
internal PublishedPropertyType(string propertyTypeAlias, string propertyEditorAlias)
|
||||
: this(propertyTypeAlias, 0, propertyEditorAlias)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedPropertyType"/> class with a property type alias and a datatype definition.
|
||||
/// </summary>
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <param name="dataTypeDefinition">The datatype definition.</param>
|
||||
/// <remarks>
|
||||
/// <para>The new published property type does not belong to a published content type.</para>
|
||||
/// </remarks>
|
||||
internal PublishedPropertyType(string propertyTypeAlias, IDataTypeDefinition dataTypeDefinition)
|
||||
: this(propertyTypeAlias, dataTypeDefinition.Id, dataTypeDefinition.PropertyEditorAlias)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedPropertyType"/> class with a property type alias,
|
||||
/// a datatype definition identifier, and a property editor alias.
|
||||
/// </summary>
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <param name="dataTypeDefinitionId">The datatype definition identifier.</param>
|
||||
/// <param name="propertyEditorAlias">The property editor alias.</param>
|
||||
/// <remarks>
|
||||
/// <para>The new published property type does not belong to a published content type.</para>
|
||||
/// <para>The values of <paramref name="dataTypeDefinitionId"/> and <paramref name="propertyEditorAlias"/> are
|
||||
/// assumed to be valid and consistent.</para>
|
||||
/// </remarks>
|
||||
internal PublishedPropertyType(string propertyTypeAlias, int dataTypeDefinitionId, string propertyEditorAlias)
|
||||
{
|
||||
// ContentType to be set by PublishedContentType when creating it
|
||||
// ContentType
|
||||
// - in unit tests, to be set by PublishedContentType when creating it
|
||||
// - in detached types, remains null
|
||||
|
||||
PropertyTypeAlias = propertyTypeAlias;
|
||||
|
||||
DataTypeId = dataTypeDefinitionId;
|
||||
@@ -43,6 +125,8 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
InitializeConverters();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Property type
|
||||
|
||||
/// <summary>
|
||||
@@ -291,5 +375,132 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Detached
|
||||
|
||||
private PropertyCacheLevel _sourceCacheLevelReduced = 0;
|
||||
private PropertyCacheLevel _objectCacheLevelReduced = 0;
|
||||
private PropertyCacheLevel _xpathCacheLevelReduced = 0;
|
||||
|
||||
internal bool IsDetachedOrNested
|
||||
{
|
||||
// enough to test source
|
||||
get { return _sourceCacheLevelReduced != 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a detached clone of this published property type.
|
||||
/// </summary>
|
||||
/// <returns>A detached clone of this published property type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Only a published property type that has not already been detached or nested, can be detached.</para>
|
||||
/// <para>Use detached published property type when creating detached properties outside of a published content.</para>
|
||||
/// </remarks>
|
||||
internal PublishedPropertyType Detached()
|
||||
{
|
||||
// verify
|
||||
if (IsDetachedOrNested)
|
||||
throw new Exception("PublishedPropertyType is already detached/nested.");
|
||||
|
||||
var detached = new PublishedPropertyType(this);
|
||||
detached._sourceCacheLevel
|
||||
= detached._objectCacheLevel
|
||||
= detached._xpathCacheLevel
|
||||
= PropertyCacheLevel.Content;
|
||||
// set to none to a) indicate it's detached / nested and b) make sure any nested
|
||||
// types switch all their cache to .Content
|
||||
detached._sourceCacheLevelReduced
|
||||
= detached._objectCacheLevelReduced
|
||||
= detached._xpathCacheLevelReduced
|
||||
= PropertyCacheLevel.None;
|
||||
|
||||
return detached;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a nested clone of this published property type within a specified container published property type.
|
||||
/// </summary>
|
||||
/// <param name="containerType">The container published property type.</param>
|
||||
/// <returns>A nested clone of this published property type</returns>
|
||||
/// <remarks>
|
||||
/// <para>Only a published property type that has not already been detached or nested, can be nested.</para>
|
||||
/// <para>Use nested published property type when creating detached properties within a published content.</para>
|
||||
/// </remarks>
|
||||
internal PublishedPropertyType Nested(PublishedPropertyType containerType)
|
||||
{
|
||||
// verify
|
||||
if (IsDetachedOrNested)
|
||||
throw new Exception("PublishedPropertyType is already detached/nested.");
|
||||
|
||||
var nested = new PublishedPropertyType(this);
|
||||
|
||||
// before we reduce, both xpath and object are >= source, and
|
||||
// the way reduce works, the relative order of resulting xpath, object and source are preserved
|
||||
|
||||
// Reduce() will set _xxxCacheLevelReduced thus indicating that the type is detached / nested
|
||||
|
||||
Reduce(_sourceCacheLevel, _sourceCacheLevelReduced, ref nested._sourceCacheLevel, ref nested._sourceCacheLevelReduced);
|
||||
Reduce(_objectCacheLevel, _objectCacheLevelReduced, ref nested._objectCacheLevel, ref nested._objectCacheLevelReduced);
|
||||
Reduce(_xpathCacheLevel, _xpathCacheLevelReduced, ref nested._xpathCacheLevel, ref nested._xpathCacheLevelReduced);
|
||||
|
||||
return nested;
|
||||
}
|
||||
|
||||
private static void Reduce(
|
||||
PropertyCacheLevel containerCacheLevel, PropertyCacheLevel containerCacheLevelReduced,
|
||||
ref PropertyCacheLevel nestedCacheLevel, ref PropertyCacheLevel nestedCacheLevelReduced)
|
||||
{
|
||||
// initialize if required
|
||||
if (containerCacheLevelReduced == 0)
|
||||
containerCacheLevelReduced = containerCacheLevel;
|
||||
|
||||
switch (containerCacheLevelReduced)
|
||||
{
|
||||
case PropertyCacheLevel.None:
|
||||
// once .None, force .Content for everything
|
||||
nestedCacheLevel = PropertyCacheLevel.Content;
|
||||
nestedCacheLevelReduced = PropertyCacheLevel.None; // and propagate
|
||||
break;
|
||||
|
||||
case PropertyCacheLevel.Request:
|
||||
// once .Request, force .Content for everything
|
||||
nestedCacheLevel = PropertyCacheLevel.Content;
|
||||
nestedCacheLevelReduced = PropertyCacheLevel.Request; // and propagate
|
||||
break;
|
||||
|
||||
case PropertyCacheLevel.Content:
|
||||
// as long as .Content, accept anything
|
||||
nestedCacheLevelReduced = nestedCacheLevel; // and it becomes the nested reduced
|
||||
break;
|
||||
|
||||
case PropertyCacheLevel.ContentCache:
|
||||
// once .ContentCache, accept .Request and .Content but not .ContentCache
|
||||
switch (nestedCacheLevel)
|
||||
{
|
||||
case PropertyCacheLevel.Request:
|
||||
case PropertyCacheLevel.None:
|
||||
// accept
|
||||
nestedCacheLevelReduced = nestedCacheLevel; // and it becomes the nested reduced
|
||||
break;
|
||||
case PropertyCacheLevel.Content:
|
||||
// accept
|
||||
nestedCacheLevelReduced = PropertyCacheLevel.ContentCache; // and propagate
|
||||
break;
|
||||
case PropertyCacheLevel.ContentCache:
|
||||
// force .Content
|
||||
nestedCacheLevel = PropertyCacheLevel.Content;
|
||||
nestedCacheLevelReduced = PropertyCacheLevel.ContentCache; // and propagate
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported PropertyCacheLevel value.");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("Unsupported PropertyCacheLevel value.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,5 +107,6 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
get { return _relationType.Id; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -127,5 +127,6 @@ namespace Umbraco.Core.Models
|
||||
}, _childObjectType, ChildObjectTypeSelector);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
@@ -34,7 +35,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
UpdateDate = updateDate;
|
||||
CreateDate = createDate;
|
||||
Key = Id.ToString().EncodeAsGuid();
|
||||
Key = Id.ToString(CultureInfo.InvariantCulture).EncodeAsGuid();
|
||||
Id = id;
|
||||
ServerAddress = serverAddress;
|
||||
ComputerName = computerName;
|
||||
@@ -51,7 +52,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
CreateDate = createDate;
|
||||
UpdateDate = createDate;
|
||||
Key = 0.ToString().EncodeAsGuid();
|
||||
Key = 0.ToString(CultureInfo.InvariantCulture).EncodeAsGuid();
|
||||
ServerAddress = serverAddress;
|
||||
ComputerName = computerName;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class TaggedEntity
|
||||
{
|
||||
public TaggedEntity(int entityId, IEnumerable<TaggedProperty> taggedProperties)
|
||||
{
|
||||
EntityId = entityId;
|
||||
TaggedProperties = taggedProperties;
|
||||
}
|
||||
|
||||
public int EntityId { get; private set; }
|
||||
public IEnumerable<TaggedProperty> TaggedProperties { get; private set; }
|
||||
}
|
||||
|
||||
public class TaggedProperty
|
||||
{
|
||||
public TaggedProperty(int propertyTypeId, string propertyTypeAlias, IEnumerable<Tag> tags)
|
||||
{
|
||||
PropertyTypeId = propertyTypeId;
|
||||
PropertyTypeAlias = propertyTypeAlias;
|
||||
Tags = tags;
|
||||
}
|
||||
|
||||
public int PropertyTypeId { get; private set; }
|
||||
public string PropertyTypeAlias { get; private set; }
|
||||
public IEnumerable<Tag> Tags { get; private set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class Tag : Entity, ITag
|
||||
|
||||
@@ -132,5 +132,6 @@ namespace Umbraco.Core.Models
|
||||
}, _comment, CommentSelector);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -14,20 +16,18 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class Template : File, ITemplate
|
||||
{
|
||||
private readonly string _alias;
|
||||
private readonly string _name;
|
||||
private string _alias;
|
||||
private string _name;
|
||||
private int _creatorId;
|
||||
private int _level;
|
||||
private int _sortOrder;
|
||||
private int _parentId;
|
||||
private int _masterTemplateId;
|
||||
private string _masterTemplateAlias;
|
||||
|
||||
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.CreatorId);
|
||||
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.Level);
|
||||
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.SortOrder);
|
||||
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.ParentId);
|
||||
//private static readonly PropertyInfo MasterTemplateIdSelector = ExpressionHelper.GetPropertyInfo<Template, int>(x => x.MasterTemplateId);
|
||||
private static readonly PropertyInfo MasterTemplateAliasSelector = ExpressionHelper.GetPropertyInfo<Template, string>(x => x.MasterTemplateAlias);
|
||||
|
||||
public Template(string path, string name, string alias)
|
||||
@@ -35,8 +35,8 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
base.Path = path;
|
||||
ParentId = -1;
|
||||
_name = name.Replace("/", ".").Replace("\\", "");
|
||||
_alias = alias.ToSafeAlias();
|
||||
_name = name; //.Replace("/", ".").Replace("\\", ""); // why? that's just the name!
|
||||
_alias = alias.ToCleanString(CleanStringType.UnderscoreAlias);
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
@@ -189,5 +189,18 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
MasterTemplateId = new Lazy<int>(() => masterTemplate.Id);
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Template)base.DeepClone();
|
||||
|
||||
//need to manually assign since they are readonly properties
|
||||
clone._alias = Alias;
|
||||
clone._name = Name;
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -283,15 +285,59 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
public IList<UmbracoProperty> UmbracoProperties { get; set; }
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (UmbracoEntity) base.DeepClone();
|
||||
|
||||
internal class UmbracoProperty
|
||||
//This ensures that any value in the dictionary that is deep cloneable is cloned too
|
||||
foreach (var key in clone.AdditionalData.Keys.ToArray())
|
||||
{
|
||||
var deepCloneable = clone.AdditionalData[key] as IDeepCloneable;
|
||||
if (deepCloneable != null)
|
||||
{
|
||||
clone.AdditionalData[key] = deepCloneable.DeepClone();
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A struction that can be contained in the additional data of an UmbracoEntity representing
|
||||
/// a user defined property
|
||||
/// </summary>
|
||||
public class EntityProperty : IDeepCloneable
|
||||
{
|
||||
public string PropertyEditorAlias { get; set; }
|
||||
public string Value { get; set; }
|
||||
public object Value { get; set; }
|
||||
public object DeepClone()
|
||||
{
|
||||
//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 clone = MemberwiseClone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected bool Equals(EntityProperty other)
|
||||
{
|
||||
return PropertyEditorAlias.Equals(other.PropertyEditorAlias) && string.Equals(Value, other.Value);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((EntityProperty) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (PropertyEditorAlias.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,10 +85,9 @@ namespace Umbraco.Core.ObjectResolution
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether a the singleton nstance has been set.
|
||||
/// Gets a value indicating whether a the singleton instance has been set.
|
||||
/// </summary>
|
||||
/// <remarks>To be used in unit tests.</remarks>
|
||||
internal static bool HasCurrent
|
||||
public static bool HasCurrent
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -102,9 +101,13 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Resets the resolver singleton instance to null.
|
||||
/// </summary>
|
||||
/// <remarks>To be used in unit tests.</remarks>
|
||||
/// <param name="resetResolution">By default this is true because we always need to reset resolution before we reset a resolver, however in some insanely rare cases like unit testing you might not want to do this.</param>
|
||||
internal static void Reset(bool resetResolution = true)
|
||||
/// <remarks>
|
||||
/// To be used in unit tests. DO NOT USE THIS DURING PRODUCTION.
|
||||
/// </remarks>
|
||||
/// <param name="resetResolution">
|
||||
/// By default this is true because we always need to reset resolution before we reset a resolver, however in some insanely rare cases like unit testing you might not want to do this.
|
||||
/// </param>
|
||||
protected internal static void Reset(bool resetResolution = true)
|
||||
{
|
||||
|
||||
//In order to reset a resolver, we always must reset the resolution
|
||||
|
||||
@@ -37,7 +37,10 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
var containsKey = _cache.ContainsKey(compositeKey);
|
||||
if (containsKey)
|
||||
{
|
||||
return _cache[compositeKey];
|
||||
var result = _cache[compositeKey];
|
||||
|
||||
//IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
||||
return (IEntity)result.DeepClone();
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -56,7 +59,12 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
into key
|
||||
let containsKey = _cache.ContainsKey(key)
|
||||
where containsKey
|
||||
select _cache[key]).ToList();
|
||||
select _cache[key]
|
||||
into result
|
||||
//don't return null objects
|
||||
where result != null
|
||||
//IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
||||
select (IEntity)result.DeepClone()).ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -67,7 +75,14 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
/// <returns></returns>
|
||||
public IEnumerable<IEntity> GetAllByType(Type type)
|
||||
{
|
||||
var list = _cache.Keys.Where(key => key.Contains(type.Name)).Select(key => _cache[key]).ToList();
|
||||
var list = _cache.Keys
|
||||
.Where(key => key.Contains(type.Name))
|
||||
.Select(key => _cache[key])
|
||||
//don't return null objects
|
||||
.Where(result => result != null)
|
||||
//IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
||||
.Select(result => (IEntity)result.DeepClone())
|
||||
.ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -78,6 +93,9 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
/// <param name="entity"></param>
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
//IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259
|
||||
entity = (IEntity)entity.DeepClone();
|
||||
|
||||
_cache.AddOrUpdate(GetCompositeId(type, entity.Id), entity, (x, y) => entity);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -29,6 +29,9 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
/// when there are async requests being made even in the context of a web request, the HttpContext.Current will be null but the HttpRuntime.Cache will
|
||||
/// always be available.
|
||||
///
|
||||
/// TODO: Each item that get's added to this cache will be a clone of the original with it's dirty properties reset, and every item that is resolved from the cache
|
||||
/// is a clone of the item that is in there, otherwise we end up with thread safety issues since multiple thread would be working on the exact same entity at the same time.
|
||||
///
|
||||
/// </remarks>
|
||||
internal sealed class RuntimeCacheProvider : IRepositoryCacheProvider
|
||||
{
|
||||
@@ -64,8 +67,11 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
{
|
||||
//ensure the key doesn't exist anymore in the tracker
|
||||
_keyTracker.Remove(key);
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
|
||||
//IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
||||
return (IEntity)result.DeepClone();
|
||||
}
|
||||
|
||||
public IEnumerable<IEntity> GetByIds(Type type, List<Guid> ids)
|
||||
@@ -85,7 +91,8 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
}
|
||||
else
|
||||
{
|
||||
collection.Add(result);
|
||||
//IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
||||
collection.Add((IEntity)result.DeepClone());
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
@@ -110,7 +117,8 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
}
|
||||
else
|
||||
{
|
||||
collection.Add(result);
|
||||
//IMPORTANT: we must clone to resolve, see: http://issues.umbraco.org/issue/U4-4259
|
||||
collection.Add((IEntity)result.DeepClone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,6 +127,9 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
//IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259
|
||||
entity = (IEntity)entity.DeepClone();
|
||||
|
||||
var key = GetCompositeId(type, entity.Id);
|
||||
|
||||
_keyTracker.TryAdd(key);
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
ContentTypeAlias = asDictionary.ContainsKey("alias") ? (d.alias ?? string.Empty) : string.Empty,
|
||||
ContentTypeIcon = asDictionary.ContainsKey("icon") ? (d.icon ?? string.Empty) : string.Empty,
|
||||
ContentTypeThumbnail = asDictionary.ContainsKey("thumbnail") ? (d.thumbnail ?? string.Empty) : string.Empty,
|
||||
UmbracoProperties = new List<UmbracoEntity.UmbracoProperty>()
|
||||
};
|
||||
|
||||
var publishedVersion = default(Guid);
|
||||
@@ -87,7 +86,6 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
ContentTypeAlias = dto.Alias ?? string.Empty,
|
||||
ContentTypeIcon = dto.Icon ?? string.Empty,
|
||||
ContentTypeThumbnail = dto.Thumbnail ?? string.Empty,
|
||||
UmbracoProperties = new List<UmbracoEntity.UmbracoProperty>()
|
||||
};
|
||||
|
||||
entity.IsPublished = dto.PublishedVersion != default(Guid) || (dto.NewestVersion != default(Guid) && dto.PublishedVersion == dto.NewestVersion);
|
||||
@@ -98,12 +96,13 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
foreach (var propertyDto in dto.UmbracoPropertyDtos)
|
||||
{
|
||||
entity.UmbracoProperties.Add(new UmbracoEntity.UmbracoProperty
|
||||
{
|
||||
PropertyEditorAlias =
|
||||
propertyDto.PropertyEditorAlias,
|
||||
Value = propertyDto.UmbracoFile
|
||||
});
|
||||
entity.AdditionalData[propertyDto.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = propertyDto.PropertyEditorAlias,
|
||||
Value = propertyDto.NTextValue.IsNullOrWhiteSpace()
|
||||
? propertyDto.NVarcharValue
|
||||
: propertyDto.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
AppAlias = app
|
||||
};
|
||||
if (entity.Id != null)
|
||||
if (entity.HasIdentity)
|
||||
{
|
||||
appDto.UserId = (int) entity.Id;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="Tag"/> to DTO mapper used to translate the properties of the public api
|
||||
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
|
||||
/// </summary>
|
||||
[MapperFor(typeof(Tag))]
|
||||
[MapperFor(typeof(ITag))]
|
||||
public sealed class TagMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
public TagMapper()
|
||||
{
|
||||
BuildMap();
|
||||
}
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
if (PropertyInfoCache.IsEmpty)
|
||||
{
|
||||
CacheMap<Tag, TagDto>(src => src.Id, dto => dto.Id);
|
||||
CacheMap<Tag, TagDto>(src => src.Text, dto => dto.Tag);
|
||||
CacheMap<Tag, TagDto>(src => src.Group, dto => dto.Group);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
.Where(x => x.IsNullOrWhiteSpace() == false).ToList();
|
||||
|
||||
//Add valid and invalid foreign key differences to the result object
|
||||
// We'll need to do invariant contains with case insensitivity because foreign key, primary key, and even index naming w/ MySQL is not standardized
|
||||
// In theory you could have: FK_ or fk_ ...or really any standard that your development department (or developer) chooses to use.
|
||||
foreach (var unknown in unknownConstraintsInDatabase)
|
||||
{
|
||||
if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown) || indexesInSchema.InvariantContains(unknown))
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
return new Version(4, 7, 0);
|
||||
}
|
||||
|
||||
return new Version(4, 9, 0);
|
||||
return new Version(4, 8, 0);
|
||||
}
|
||||
|
||||
//if the error is for umbracoServer
|
||||
|
||||
@@ -46,20 +46,20 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
{
|
||||
LogHelper.Info<MigrationRunner>("Initializing database migrations");
|
||||
|
||||
var foundMigrations = MigrationResolver.Current.Migrations.ToArray();
|
||||
var foundMigrations = MigrationResolver.Current.Migrations.ToArray();
|
||||
|
||||
//filter all non-schema migrations
|
||||
var migrations = isUpgrade
|
||||
? OrderedUpgradeMigrations(foundMigrations).ToList()
|
||||
: OrderedDowngradeMigrations(foundMigrations).ToList();
|
||||
|
||||
|
||||
//SD: Why do we want this?
|
||||
if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrations, _currentVersion, _targetVersion, true), this))
|
||||
return false;
|
||||
|
||||
//Loop through migrations to generate sql
|
||||
var migrationContext = InitializeMigrations(migrations, database, databaseProvider, isUpgrade);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteMigrations(migrationContext, database);
|
||||
@@ -86,8 +86,8 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ExecuteMigrations(IMigrationContext context, Database database)
|
||||
{
|
||||
private void ExecuteMigrations(IMigrationContext context, Database database)
|
||||
{
|
||||
//Transactional execution of the sql that was generated from the found migrations
|
||||
using (var transaction = database.GetTransaction())
|
||||
{
|
||||
@@ -108,13 +108,13 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
|
||||
transaction.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal MigrationContext InitializeMigrations(List<IMigration> migrations, Database database, DatabaseProviders databaseProvider, bool isUpgrade = true)
|
||||
{
|
||||
{
|
||||
//Loop through migrations to generate sql
|
||||
var context = new MigrationContext(databaseProvider, database);
|
||||
|
||||
|
||||
foreach (var migration in migrations)
|
||||
{
|
||||
var baseMigration = migration as MigrationBase;
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters and orders migrations based on the migrations listed and the currently configured version and the target installation version
|
||||
@@ -158,17 +158,17 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
internal IEnumerable<IMigration> OrderedUpgradeMigrations(IEnumerable<IMigration> foundMigrations)
|
||||
{
|
||||
var migrations = (from migration in foundMigrations
|
||||
let migrationAttributes = migration.GetType().GetCustomAttributes<MigrationAttribute>(false)
|
||||
from migrationAttribute in migrationAttributes
|
||||
where migrationAttribute != null
|
||||
where
|
||||
let migrationAttributes = migration.GetType().GetCustomAttributes<MigrationAttribute>(false)
|
||||
from migrationAttribute in migrationAttributes
|
||||
where migrationAttribute != null
|
||||
where
|
||||
migrationAttribute.TargetVersion > _currentVersion &&
|
||||
migrationAttribute.TargetVersion <= _targetVersion &&
|
||||
migrationAttribute.TargetVersion <= _targetVersion &&
|
||||
migrationAttribute.ProductName == _productName &&
|
||||
//filter if the migration specifies a minimum current version for which to execute
|
||||
(migrationAttribute.MinimumCurrentVersion == null || _currentVersion >= migrationAttribute.MinimumCurrentVersion)
|
||||
orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder ascending
|
||||
select migration).Distinct();
|
||||
orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder ascending
|
||||
select migration).Distinct();
|
||||
return migrations;
|
||||
}
|
||||
|
||||
@@ -180,17 +180,17 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
public IEnumerable<IMigration> OrderedDowngradeMigrations(IEnumerable<IMigration> foundMigrations)
|
||||
{
|
||||
var migrations = (from migration in foundMigrations
|
||||
let migrationAttributes = migration.GetType().GetCustomAttributes<MigrationAttribute>(false)
|
||||
from migrationAttribute in migrationAttributes
|
||||
where migrationAttribute != null
|
||||
where
|
||||
let migrationAttributes = migration.GetType().GetCustomAttributes<MigrationAttribute>(false)
|
||||
from migrationAttribute in migrationAttributes
|
||||
where migrationAttribute != null
|
||||
where
|
||||
migrationAttribute.TargetVersion > _currentVersion &&
|
||||
migrationAttribute.TargetVersion <= _targetVersion &&
|
||||
migrationAttribute.TargetVersion <= _targetVersion &&
|
||||
migrationAttribute.ProductName == _productName &&
|
||||
//filter if the migration specifies a minimum current version for which to execute
|
||||
(migrationAttribute.MinimumCurrentVersion == null || _currentVersion >= migrationAttribute.MinimumCurrentVersion)
|
||||
orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder descending
|
||||
select migration).Distinct();
|
||||
orderby migrationAttribute.TargetVersion, migrationAttribute.SortOrder descending
|
||||
select migration).Distinct();
|
||||
return migrations;
|
||||
}
|
||||
|
||||
|
||||
+54
-30
@@ -7,6 +7,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -32,48 +33,71 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
|
||||
var propertyData =
|
||||
database.Fetch<PropertyDataDto>(
|
||||
"WHERE propertyTypeId in (SELECT id from cmsPropertyType where dataTypeID IN (@dataTypeIds))", new { dataTypeIds = dataTypeIds });
|
||||
if (!propertyData.Any()) return string.Empty;
|
||||
|
||||
var nodesIdsWithProperty = propertyData.Select(x => x.NodeId).Distinct();
|
||||
var cmsContentXmlEntries = database.Fetch<ContentXmlDto>(
|
||||
"WHERE nodeId in (@nodeIds)", new { nodeIds = nodesIdsWithProperty });
|
||||
var propertyTypeIds = propertyData.Select(x => x.PropertyTypeId).Distinct();
|
||||
var propertyTypes = database.Fetch<PropertyTypeDto>(
|
||||
"WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds });
|
||||
|
||||
foreach (var data in propertyData)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(data.Text))
|
||||
if (string.IsNullOrEmpty(data.Text) == false)
|
||||
{
|
||||
//var cs = ApplicationContext.Current.Services.ContentService;
|
||||
|
||||
//fetch the current data (that's in xml format)
|
||||
var xml = new XmlDocument();
|
||||
xml.LoadXml(data.Text);
|
||||
|
||||
if (xml != null)
|
||||
var links = new List<ExpandoObject>();
|
||||
|
||||
//loop all the stored links
|
||||
foreach (XmlNode node in xml.DocumentElement.ChildNodes)
|
||||
{
|
||||
var links = new List<ExpandoObject>();
|
||||
var title = node.Attributes["title"].Value;
|
||||
var type = node.Attributes["type"].Value;
|
||||
var newwindow = node.Attributes["newwindow"].Value.Equals("1") ? true : false;
|
||||
var lnk = node.Attributes["link"].Value;
|
||||
|
||||
//loop all the stored links
|
||||
foreach (XmlNode node in xml.DocumentElement.ChildNodes)
|
||||
{
|
||||
var title = node.Attributes["title"].Value;
|
||||
var type = node.Attributes["type"].Value;
|
||||
var newwindow = node.Attributes["newwindow"].Value.Equals("1") ? true : false;
|
||||
var lnk = node.Attributes["link"].Value;
|
||||
//create the links in the format the new prop editor expects it to be
|
||||
var link = new ExpandoObject() as IDictionary<string, Object>;
|
||||
link.Add("title", title);
|
||||
link.Add("caption", title);
|
||||
link.Add("link", lnk);
|
||||
link.Add("newWindow", newwindow);
|
||||
link.Add("type", type.Equals("internal") ? "internal" : "external");
|
||||
link.Add("internal", type.Equals("internal") ? lnk : null);
|
||||
|
||||
//create the links in the format the new prop editor expects it to be
|
||||
var link = new ExpandoObject() as IDictionary<string, Object>;
|
||||
link.Add("title", title);
|
||||
link.Add("caption", title);
|
||||
link.Add("link", lnk);
|
||||
link.Add("newWindow", newwindow);
|
||||
link.Add("type", type.Equals("internal") ? "internal" : "external");
|
||||
link.Add("internal", type.Equals("internal") ? lnk : null);
|
||||
link.Add("edit", false);
|
||||
link.Add("isInternal", type.Equals("internal"));
|
||||
|
||||
link.Add("edit", false);
|
||||
link.Add("isInternal", type.Equals("internal"));
|
||||
|
||||
links.Add((ExpandoObject)link);
|
||||
}
|
||||
|
||||
//store the serialized data
|
||||
data.Text = JsonConvert.SerializeObject(links);
|
||||
|
||||
database.Update(data);
|
||||
links.Add((ExpandoObject)link);
|
||||
}
|
||||
|
||||
//store the serialized data
|
||||
data.Text = JsonConvert.SerializeObject(links);
|
||||
|
||||
database.Update(data);
|
||||
|
||||
//now we need to update the cmsContentXml table
|
||||
var propertyType = propertyTypes.SingleOrDefault(x => x.Id == data.PropertyTypeId);
|
||||
if (propertyType != null)
|
||||
{
|
||||
var xmlItem = cmsContentXmlEntries.SingleOrDefault(x => x.NodeId == data.NodeId);
|
||||
if (xmlItem != null)
|
||||
{
|
||||
var x = XElement.Parse(xmlItem.Xml);
|
||||
var prop = x.Element(propertyType.Alias);
|
||||
if (prop != null)
|
||||
{
|
||||
prop.ReplaceAll(new XCData(data.Text));
|
||||
database.Update(xmlItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-9
@@ -5,6 +5,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
|
||||
{
|
||||
|
||||
//see: http://issues.umbraco.org/issue/U4-4430
|
||||
[Migration("7.1.0", 0, GlobalSettings.UmbracoMigrationName)]
|
||||
[Migration("6.2.0", 0, GlobalSettings.UmbracoMigrationName)]
|
||||
@@ -15,15 +16,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
|
||||
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
{
|
||||
var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
|
||||
|
||||
//This should be 2 because this table has 2 keys
|
||||
if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0)
|
||||
{
|
||||
Create.PrimaryKey("PK_cmsContentType2ContentType")
|
||||
.OnTable("cmsContentType2ContentType")
|
||||
.Columns(new[] {"parentContentTypeId", "childContentTypeId"});
|
||||
}
|
||||
|
||||
|
||||
//This should be 2 because this table has 2 keys
|
||||
if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentTypeAllowedContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0)
|
||||
{
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
|
||||
{
|
||||
//We have to target this specifically to ensure this DOES NOT execute if upgrading from a version previous to 6.0,
|
||||
// this is because when the 6.0.0 migrations are executed, this primary key get's created so if this migration is also executed
|
||||
// we will get exceptions because it is trying to create the PK two times.
|
||||
[Migration("6.0.0", "6.2.0", 0, GlobalSettings.UmbracoMigrationName)]
|
||||
public class AssignMissingPrimaryForMySqlKeys2 : MigrationBase
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
{
|
||||
var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
|
||||
|
||||
//This should be 2 because this table has 2 keys
|
||||
if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0)
|
||||
{
|
||||
Create.PrimaryKey("PK_cmsContentType2ContentType")
|
||||
.OnTable("cmsContentType2ContentType")
|
||||
.Columns(new[] {"parentContentTypeId", "childContentTypeId"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
//don't do anything, these keys should have always existed!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Private class to handle preview insert/update based on standard principles and units of work with transactions
|
||||
/// </summary>
|
||||
internal class ContentPreviewRepository<TContent> : PetaPocoRepositoryBase<int, ContentPreviewEntity<TContent>>
|
||||
where TContent : IContentBase
|
||||
{
|
||||
public ContentPreviewRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
: base(work, cache)
|
||||
{
|
||||
}
|
||||
|
||||
#region Not implemented (don't need to for the purposes of this repo)
|
||||
protected override ContentPreviewEntity<TContent> PerformGet(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentPreviewEntity<TContent>> PerformGetAll(params int[] ids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentPreviewEntity<TContent>> PerformGetByQuery(IQuery<ContentPreviewEntity<TContent>> query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override Sql GetBaseQuery(bool isCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
protected override void PersistDeletedItem(ContentPreviewEntity<TContent> entity)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override void PersistNewItem(ContentPreviewEntity<TContent> entity)
|
||||
{
|
||||
if (entity.Content.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot insert a preview for a content item that has no identity");
|
||||
}
|
||||
|
||||
var previewPoco = new PreviewXmlDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Timestamp = DateTime.Now,
|
||||
VersionId = entity.Version,
|
||||
Xml = entity.Xml.ToString(SaveOptions.None)
|
||||
};
|
||||
|
||||
Database.Insert(previewPoco);
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(ContentPreviewEntity<TContent> entity)
|
||||
{
|
||||
if (entity.Content.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot update a preview for a content item that has no identity");
|
||||
}
|
||||
|
||||
var previewPoco = new PreviewXmlDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Timestamp = DateTime.Now,
|
||||
VersionId = entity.Version,
|
||||
Xml = entity.Xml.ToString(SaveOptions.None)
|
||||
};
|
||||
|
||||
Database.Update<PreviewXmlDto>(
|
||||
"SET xml = @Xml, timestamp = @Timestamp WHERE nodeId = @Id AND versionId = @Version",
|
||||
new
|
||||
{
|
||||
Xml = previewPoco.Xml,
|
||||
Timestamp = previewPoco.Timestamp,
|
||||
Id = previewPoco.NodeId,
|
||||
Version = previewPoco.VersionId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -12,6 +14,7 @@ using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
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
|
||||
@@ -25,6 +28,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
private readonly ITemplateRepository _templateRepository;
|
||||
private readonly ITagsRepository _tagRepository;
|
||||
private readonly CacheHelper _cacheHelper;
|
||||
private readonly ContentPreviewRepository<IContent> _contentPreviewRepository;
|
||||
private readonly ContentXmlRepository<IContent> _contentXmlRepository;
|
||||
|
||||
public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository, CacheHelper cacheHelper)
|
||||
: base(work)
|
||||
@@ -36,6 +41,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
_templateRepository = templateRepository;
|
||||
_tagRepository = tagRepository;
|
||||
_cacheHelper = cacheHelper;
|
||||
_contentPreviewRepository = new ContentPreviewRepository<IContent>(work, NullCacheProvider.Current);
|
||||
_contentXmlRepository = new ContentXmlRepository<IContent>(work, NullCacheProvider.Current);
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
@@ -50,6 +57,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
_templateRepository = templateRepository;
|
||||
_tagRepository = tagRepository;
|
||||
_cacheHelper = cacheHelper;
|
||||
_contentPreviewRepository = new ContentPreviewRepository<IContent>(work, NullCacheProvider.Current);
|
||||
_contentXmlRepository = new ContentXmlRepository<IContent>(work, NullCacheProvider.Current);
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
@@ -149,12 +158,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"DELETE FROM umbracoRelation WHERE childId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoDomains WHERE domainRootStructureID = @Id",
|
||||
"DELETE FROM cmsDocument WHERE NodeId = @Id",
|
||||
"DELETE FROM cmsDocument WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsPropertyData WHERE contentNodeId = @Id",
|
||||
"DELETE FROM cmsPreviewXml WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsContentVersion WHERE ContentId = @Id",
|
||||
"DELETE FROM cmsContentXml WHERE nodeID = @Id",
|
||||
"DELETE FROM cmsContent WHERE NodeId = @Id",
|
||||
"DELETE FROM cmsContentXml WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsContent WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
@@ -433,7 +442,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
//In order to update the ContentVersion we need to retreive its primary key id
|
||||
//In order to update the ContentVersion we need to retrieve its primary key id
|
||||
var contentVerDto = Database.SingleOrDefault<ContentVersionDto>("WHERE VersionId = @Version", new { Version = entity.Version });
|
||||
contentVersionDto.Id = contentVerDto.Id;
|
||||
|
||||
@@ -516,11 +525,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public IEnumerable<IContent> GetByPublishedVersion(IQuery<IContent> query)
|
||||
{
|
||||
// we WANT to return contents in top-down order, ie parents should come before children
|
||||
// ideal would be pure xml "document order" which can be achieved with:
|
||||
// ORDER BY substring(path, 1, len(path) - charindex(',', reverse(path))), sortOrder
|
||||
// but that's probably an overkill - sorting by level,sortOrder should be enough
|
||||
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IContent>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.Where<DocumentDto>(x => x.Published)
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate)
|
||||
.OrderBy<NodeDto>(x => x.Level)
|
||||
.OrderBy<NodeDto>(x => x.SortOrder);
|
||||
|
||||
//NOTE: This doesn't allow properties to be part of the query
|
||||
@@ -577,6 +591,41 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return repo.GetPermissionsForEntity(entityId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds/updates content/published xml
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
public void AddOrUpdateContentXml(IContent content, Func<IContent, XElement> xml)
|
||||
{
|
||||
var contentExists = Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
|
||||
|
||||
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity<IContent>(contentExists, content, xml));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to remove the content xml for a content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
public void DeleteContentXml(IContent content)
|
||||
{
|
||||
_contentXmlRepository.Delete(new ContentXmlEntity<IContent>(content));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds/updates preview xml
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
public void AddOrUpdatePreviewXml(IContent content, Func<IContent, XElement> xml)
|
||||
{
|
||||
var previewExists =
|
||||
Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
|
||||
new { Id = content.Id, Version = content.Version }) != 0;
|
||||
|
||||
_contentPreviewRepository.AddOrUpdate(new ContentPreviewEntity<IContent>(previewExists, content, xml));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -637,5 +686,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
return currentName;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"DELETE FROM cmsPropertyType WHERE contentTypeId = @Id",
|
||||
"DELETE FROM cmsPropertyTypeGroup WHERE contenttypeNodeId = @Id",
|
||||
"DELETE FROM cmsDocumentType WHERE contentTypeNodeId = @Id",
|
||||
"DELETE FROM cmsContentType WHERE NodeId = @Id",
|
||||
"DELETE FROM cmsContentType WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal class to handle content/published xml insert/update based on standard principles and units of work with transactions
|
||||
/// </summary>
|
||||
internal class ContentXmlRepository<TContent> : PetaPocoRepositoryBase<int, ContentXmlEntity<TContent>>
|
||||
where TContent : IContentBase
|
||||
{
|
||||
public ContentXmlRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
: base(work, cache)
|
||||
{
|
||||
}
|
||||
|
||||
#region Not implemented (don't need to for the purposes of this repo)
|
||||
protected override ContentXmlEntity<TContent> PerformGet(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentXmlEntity<TContent>> PerformGetAll(params int[] ids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentXmlEntity<TContent>> PerformGetByQuery(IQuery<ContentXmlEntity<TContent>> query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override Sql GetBaseQuery(bool isCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void PersistDeletedItem(ContentXmlEntity<TContent> entity)
|
||||
{
|
||||
//Remove 'published' xml from the cmsContentXml table for the unpublished content
|
||||
Database.Delete<ContentXmlDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
}
|
||||
|
||||
protected override void PersistNewItem(ContentXmlEntity<TContent> entity)
|
||||
{
|
||||
if (entity.Content.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot insert an xml entry for a content item that has no identity");
|
||||
}
|
||||
|
||||
var poco = new ContentXmlDto { NodeId = entity.Id, Xml = entity.Xml.ToString(SaveOptions.None) };
|
||||
Database.Insert(poco);
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(ContentXmlEntity<TContent> entity)
|
||||
{
|
||||
if (entity.Content.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot update an xml entry for a content item that has no identity");
|
||||
}
|
||||
|
||||
var poco = new ContentXmlDto { NodeId = entity.Id, Xml = entity.Xml.ToString(SaveOptions.None) };
|
||||
Database.Update(poco);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -11,6 +13,8 @@ using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Services;
|
||||
using NullCacheProvider = Umbraco.Core.Persistence.Caching.NullCacheProvider;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
@@ -19,16 +23,30 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
internal class DataTypeDefinitionRepository : PetaPocoRepositoryBase<int, IDataTypeDefinition>, IDataTypeDefinitionRepository
|
||||
{
|
||||
public DataTypeDefinitionRepository(IDatabaseUnitOfWork work)
|
||||
private readonly CacheHelper _cacheHelper;
|
||||
private readonly IContentTypeRepository _contentTypeRepository;
|
||||
private readonly DataTypePreValueRepository _preValRepository;
|
||||
|
||||
public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper,
|
||||
IContentTypeRepository contentTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
_cacheHelper = cacheHelper;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_preValRepository = new DataTypePreValueRepository(work, NullCacheProvider.Current);
|
||||
}
|
||||
|
||||
public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, CacheHelper cacheHelper,
|
||||
IContentTypeRepository contentTypeRepository)
|
||||
: base(work, cache)
|
||||
{
|
||||
_cacheHelper = cacheHelper;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_preValRepository = new DataTypePreValueRepository(work, NullCacheProvider.Current);
|
||||
}
|
||||
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
|
||||
|
||||
#region Overrides of RepositoryBase<int,DataTypeDefinition>
|
||||
|
||||
protected override IDataTypeDefinition PerformGet(int id)
|
||||
@@ -83,6 +101,37 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override the delete method so that we can ensure that all related content type's are updated as part of the overall transaction
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public override void Delete(IDataTypeDefinition entity)
|
||||
{
|
||||
//Find ContentTypes using this IDataTypeDefinition on a PropertyType
|
||||
var query = Query<PropertyType>.Builder.Where(x => x.DataTypeDefinitionId == entity.Id);
|
||||
var contentTypes = _contentTypeRepository.GetByQuery(query);
|
||||
|
||||
//Loop through the list of results and remove the PropertyTypes that references the DataTypeDefinition that is being deleted
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
if (contentType == null) continue;
|
||||
|
||||
foreach (var group in contentType.PropertyGroups)
|
||||
{
|
||||
var types = @group.PropertyTypes.Where(x => x.DataTypeDefinitionId == entity.Id).ToList();
|
||||
foreach (var propertyType in types)
|
||||
{
|
||||
@group.PropertyTypes.Remove(propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
_contentTypeRepository.AddOrUpdate(contentType);
|
||||
}
|
||||
|
||||
//call the base method to queue the deletion of this data type
|
||||
base.Delete(entity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of PetaPocoRepositoryBase<int,DataTypeDefinition>
|
||||
@@ -238,5 +287,322 @@ AND umbracoNode.id <> @id",
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId)
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache
|
||||
return cached.First();
|
||||
}
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
return GetAndCachePreValueCollection(dataTypeId);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetPreValueAsString(int preValueId)
|
||||
{
|
||||
using (var l = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
//We need to see if we can find the cached PreValueCollection based on the cache key above
|
||||
|
||||
var regex = CacheKeys.DataTypePreValuesCacheKey + @"[\d]+-[,\d]*" + preValueId + @"[,\d$]*";
|
||||
|
||||
var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeyExpression<PreValueCollection>(regex);
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache
|
||||
var collection = cached.First();
|
||||
var preVal = collection.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
||||
return preVal.Value.Value;
|
||||
}
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
//go and find the data type id for the pre val id passed in
|
||||
|
||||
var dto = Database.FirstOrDefault<DataTypePreValueDto>("WHERE id = @preValueId", new { preValueId = preValueId });
|
||||
if (dto == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
// go cache the collection
|
||||
var preVals = GetAndCachePreValueCollection(dto.DataTypeNodeId);
|
||||
|
||||
//return the single value for this id
|
||||
var pv = preVals.FormatAsDictionary().Single(x => x.Value.Id == preValueId);
|
||||
return pv.Value.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values)
|
||||
{
|
||||
var dtd = Get(dataTypeId);
|
||||
if (dtd == null)
|
||||
{
|
||||
throw new InvalidOperationException("No data type found with id " + dataTypeId);
|
||||
}
|
||||
AddOrUpdatePreValues(dtd, values);
|
||||
}
|
||||
|
||||
public void AddOrUpdatePreValues(IDataTypeDefinition dataType, IDictionary<string, PreValue> values)
|
||||
{
|
||||
var currentVals = new DataTypePreValueDto[]{};
|
||||
if (dataType.HasIdentity)
|
||||
{
|
||||
//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>()
|
||||
.Where<DataTypePreValueDto>(dto => dto.DataTypeNodeId == dataType.Id)
|
||||
.OrderBy<DataTypePreValueDto>(dto => dto.SortOrder);
|
||||
currentVals = Database.Fetch<DataTypePreValueDto>(sql).ToArray();
|
||||
}
|
||||
|
||||
//already existing, need to be updated
|
||||
var valueIds = values.Where(x => x.Value.Id > 0).Select(x => x.Value.Id).ToArray();
|
||||
var existingByIds = currentVals.Where(x => valueIds.Contains(x.Id)).ToArray();
|
||||
|
||||
//These ones need to be removed from the db, they no longer exist in the new values
|
||||
var deleteById = currentVals.Where(x => valueIds.Contains(x.Id) == false);
|
||||
|
||||
foreach (var d in deleteById)
|
||||
{
|
||||
_preValRepository.Delete(new PreValueEntity
|
||||
{
|
||||
Alias = d.Alias,
|
||||
Id = d.Id,
|
||||
Value = d.Value,
|
||||
DataType = dataType,
|
||||
SortOrder = d.SortOrder
|
||||
});
|
||||
}
|
||||
|
||||
var sortOrder = 1;
|
||||
|
||||
foreach (var pre in values)
|
||||
{
|
||||
var existing = existingByIds.FirstOrDefault(valueDto => valueDto.Id == pre.Value.Id);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Value = pre.Value.Value;
|
||||
existing.SortOrder = sortOrder;
|
||||
_preValRepository.AddOrUpdate(new PreValueEntity
|
||||
{
|
||||
//setting an id will update it
|
||||
Id = existing.Id,
|
||||
Alias = existing.Alias,
|
||||
SortOrder = existing.SortOrder,
|
||||
Value = existing.Value,
|
||||
DataType = dataType,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_preValRepository.AddOrUpdate(new PreValueEntity
|
||||
{
|
||||
Alias = pre.Key,
|
||||
SortOrder = sortOrder,
|
||||
Value = pre.Value.Value,
|
||||
DataType = dataType,
|
||||
});
|
||||
}
|
||||
|
||||
sortOrder++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string GetPrefixedCacheKey(int dataTypeId)
|
||||
{
|
||||
return CacheKeys.DataTypePreValuesCacheKey + dataTypeId + "-";
|
||||
}
|
||||
|
||||
private PreValueCollection GetAndCachePreValueCollection(int dataTypeId)
|
||||
{
|
||||
//go get the data
|
||||
var dtos = Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = dataTypeId });
|
||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value), x.Alias, x.SortOrder)).ToList();
|
||||
var collection = PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
|
||||
//now create the cache key, this needs to include all pre-value ids so that we can use this cached item in the GetPreValuesAsString method
|
||||
//the key will be: "UmbracoPreValDATATYPEID-CSVOFPREVALIDS
|
||||
|
||||
var key = GetPrefixedCacheKey(dataTypeId)
|
||||
+ string.Join(",", collection.FormatAsDictionary().Select(x => x.Value.Id).ToArray());
|
||||
|
||||
//store into cache
|
||||
_cacheHelper.RuntimeCache.InsertCacheItem(key, () => collection,
|
||||
//30 mins
|
||||
new TimeSpan(0, 0, 30),
|
||||
//sliding is true
|
||||
true);
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private class to handle pre-value crud based on units of work with transactions
|
||||
/// </summary>
|
||||
private class PreValueEntity : Entity, IAggregateRoot
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public IDataTypeDefinition DataType { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private class to handle pre-value crud based on standard principles and units of work with transactions
|
||||
/// </summary>
|
||||
private class DataTypePreValueRepository : PetaPocoRepositoryBase<int, PreValueEntity>
|
||||
{
|
||||
public DataTypePreValueRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache)
|
||||
{
|
||||
}
|
||||
|
||||
#region Not implemented (don't need to for the purposes of this repo)
|
||||
protected override PreValueEntity PerformGet(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<PreValueEntity> PerformGetAll(params int[] ids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<PreValueEntity> PerformGetByQuery(IQuery<PreValueEntity> query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override Sql GetBaseQuery(bool isCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override void PersistDeletedItem(PreValueEntity entity)
|
||||
{
|
||||
Database.Execute(
|
||||
"DELETE FROM cmsDataTypePreValues WHERE id=@Id",
|
||||
new { Id = entity.Id });
|
||||
}
|
||||
|
||||
protected override void PersistNewItem(PreValueEntity entity)
|
||||
{
|
||||
if (entity.DataType.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot insert a pre value for a data type that has no identity");
|
||||
}
|
||||
|
||||
//Cannot add a duplicate alias
|
||||
var exists = Database.ExecuteScalar<int>(@"SELECT COUNT(*) FROM cmsDataTypePreValues
|
||||
WHERE alias = @alias
|
||||
AND datatypeNodeId = @dtdid",
|
||||
new { alias = entity.Alias, dtdid = entity.DataType.Id });
|
||||
if (exists > 0)
|
||||
{
|
||||
throw new DuplicateNameException("A pre value with the alias " + entity.Alias + " already exists for this data type");
|
||||
}
|
||||
|
||||
var dto = new DataTypePreValueDto
|
||||
{
|
||||
DataTypeNodeId = entity.DataType.Id,
|
||||
Value = entity.Value,
|
||||
SortOrder = entity.SortOrder,
|
||||
Alias = entity.Alias
|
||||
};
|
||||
Database.Insert(dto);
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(PreValueEntity entity)
|
||||
{
|
||||
if (entity.DataType.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot update a pre value for a data type that has no identity");
|
||||
}
|
||||
|
||||
//Cannot change to a duplicate alias
|
||||
var exists = Database.ExecuteScalar<int>(@"SELECT COUNT(*) FROM cmsDataTypePreValues
|
||||
WHERE alias = @alias
|
||||
AND datatypeNodeId = @dtdid
|
||||
AND id <> @id",
|
||||
new { id = entity.Id, alias = entity.Alias, dtdid = entity.DataType.Id });
|
||||
if (exists > 0)
|
||||
{
|
||||
throw new DuplicateNameException("A pre value with the alias " + entity.Alias + " already exists for this data type");
|
||||
}
|
||||
|
||||
var dto = new DataTypePreValueDto
|
||||
{
|
||||
DataTypeNodeId = entity.DataType.Id,
|
||||
Id = entity.Id,
|
||||
Value = entity.Value,
|
||||
SortOrder = entity.SortOrder,
|
||||
Alias = entity.Alias
|
||||
};
|
||||
Database.Update(dto);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PreValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the tuple to a pre-value collection
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
internal static PreValueCollection ConvertToPreValuesCollection(IEnumerable<Tuple<PreValue, string, int>> list)
|
||||
{
|
||||
//now we need to determine if they are dictionary based, otherwise they have to be array based
|
||||
var dictionary = new Dictionary<string, PreValue>();
|
||||
|
||||
//need to check all of the keys, if there's only one and it is empty then it's an array
|
||||
var keys = list.Select(x => x.Item2).Distinct().ToArray();
|
||||
if (keys.Length == 1 && keys[0].IsNullOrWhiteSpace())
|
||||
{
|
||||
return new PreValueCollection(list.OrderBy(x => x.Item3).Select(x => x.Item1));
|
||||
}
|
||||
|
||||
foreach (var item in list
|
||||
.OrderBy(x => x.Item3) //we'll order them first so we maintain the order index in the dictionary
|
||||
.GroupBy(x => x.Item2)) //group by alias
|
||||
{
|
||||
if (item.Count() > 1)
|
||||
{
|
||||
//if there's more than 1 item per key, then it cannot be a dictionary, just return the array
|
||||
return new PreValueCollection(list.OrderBy(x => x.Item3).Select(x => x.Item1));
|
||||
}
|
||||
|
||||
dictionary.Add(item.Key, item.First().Item1);
|
||||
}
|
||||
|
||||
return new PreValueCollection(dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -50,6 +50,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
foreach (var textDto in dto.LanguageTextDtos)
|
||||
{
|
||||
var language = _languageRepository.Get(textDto.LanguageId);
|
||||
if (language == null)
|
||||
continue;
|
||||
var translationFactory = new DictionaryTranslationFactory(dto.UniqueId, language);
|
||||
list.Add(translationFactory.BuildEntity(textDto));
|
||||
}
|
||||
|
||||
@@ -66,15 +66,31 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, key).Append(GetGroupBy(isContent, isMedia));
|
||||
var nodeDto = _work.Database.FirstOrDefault<dynamic>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var entity = factory.BuildEntityFromDynamic(nodeDto);
|
||||
var sql = GetFullSqlForEntityType(key, isContent, isMedia, objectTypeId);
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
|
||||
return entity;
|
||||
return entities.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDto = _work.Database.FirstOrDefault<dynamic>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var entity = factory.BuildEntityFromDynamic(nodeDto);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public virtual IUmbracoEntity Get(int id)
|
||||
@@ -94,16 +110,31 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, id).Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
var nodeDto = _work.Database.FirstOrDefault<dynamic>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
var sql = GetFullSqlForEntityType(id, isContent, isMedia, objectTypeId);
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var entity = factory.BuildEntityFromDynamic(nodeDto);
|
||||
return entities.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDto = _work.Database.FirstOrDefault<dynamic>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
|
||||
return entity;
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var entity = factory.BuildEntityFromDynamic(nodeDto);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params int[] ids)
|
||||
@@ -119,8 +150,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, string.Empty, objectTypeId).Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, string.Empty);
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
if (isMedia)
|
||||
@@ -166,24 +197,28 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>)query).WhereClauses()));
|
||||
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, wheres, objectTypeId);
|
||||
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(isContent, isMedia));
|
||||
var entitySql = translator.Translate();
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
var mediaSql = GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), wheres);
|
||||
|
||||
//treat media differently for now
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
new UmbracoEntityRelator().Map, mediaSql);
|
||||
return entities;
|
||||
}
|
||||
else
|
||||
{
|
||||
//use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData
|
||||
var dtos = _work.Database.Fetch<dynamic>(sql);
|
||||
var dtos = _work.Database.Fetch<dynamic>(entitySql.Append(GetGroupBy(isContent, false)));
|
||||
return dtos.Select(factory.BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
||||
}
|
||||
}
|
||||
@@ -193,6 +228,62 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Sql Statements
|
||||
|
||||
protected Sql GetFullSqlForEntityType(Guid key, bool isContent, bool isMedia, Guid objectTypeId)
|
||||
{
|
||||
var entitySql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, key);
|
||||
|
||||
if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false));
|
||||
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)));
|
||||
}
|
||||
|
||||
protected Sql GetFullSqlForEntityType(int id, bool isContent, bool isMedia, Guid objectTypeId)
|
||||
{
|
||||
var entitySql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId, id);
|
||||
|
||||
if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false));
|
||||
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)));
|
||||
}
|
||||
|
||||
protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, string additionalWhereClause)
|
||||
{
|
||||
var entitySql = GetBaseWhere(GetBase, isContent, isMedia, additionalWhereClause, objectTypeId);
|
||||
|
||||
if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false));
|
||||
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)));
|
||||
}
|
||||
|
||||
private Sql GetFullSqlForMedia(Sql entitySql, string additionWhereStatement = "")
|
||||
{
|
||||
//this will add any dataNvarchar property to the output which can be added to the additional properties
|
||||
|
||||
var joinSql = new Sql()
|
||||
.Select("contentNodeId, versionId, dataNvarchar, dataNtext, propertyEditorAlias, alias as propertyTypeAlias")
|
||||
.From<PropertyDataDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<PropertyDataDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.InnerJoin<PropertyTypeDto>()
|
||||
.On<PropertyTypeDto, PropertyDataDto>(dto => dto.Id, dto => dto.PropertyTypeId)
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(dto => dto.DataTypeId, dto => dto.DataTypeId)
|
||||
.Where("umbracoNode.nodeObjectType = @nodeObjectType" + additionWhereStatement, new {nodeObjectType = Constants.ObjectTypes.Media});
|
||||
|
||||
//We're going to create a query to query against the entity SQL
|
||||
// because we cannot group by nText columns and we have a COUNT in the entitySql we cannot simply left join
|
||||
// the entitySql query, we have to join the wrapped query to get the ntext in the result
|
||||
|
||||
var wrappedSql = new Sql("SELECT * FROM (")
|
||||
.Append(entitySql)
|
||||
.Append(new Sql(") tmpTbl LEFT JOIN ("))
|
||||
.Append(joinSql)
|
||||
.Append(new Sql(") as property ON id = property.contentNodeId"))
|
||||
.OrderBy("sortOrder");
|
||||
|
||||
return wrappedSql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, string additionWhereStatement = "")
|
||||
{
|
||||
var columns = new List<object>
|
||||
@@ -221,13 +312,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
columns.Add("contenttype.isContainer");
|
||||
}
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
columns.Add("property.dataNvarchar as umbracoFile");
|
||||
columns.Add("property.propertyEditorAlias");
|
||||
}
|
||||
//Creates an SQL query to return a single row for the entity
|
||||
|
||||
var sql = new Sql()
|
||||
var entitySql = new Sql()
|
||||
.Select(columns.ToArray())
|
||||
.From("umbracoNode umbracoNode")
|
||||
.LeftJoin("umbracoNode parent").On("parent.parentID = umbracoNode.id");
|
||||
@@ -235,7 +322,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
sql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id")
|
||||
entitySql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id")
|
||||
.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType")
|
||||
.LeftJoin(
|
||||
"(SELECT nodeId, versionId FROM cmsDocument WHERE published = 1 GROUP BY nodeId, versionId) as published")
|
||||
@@ -245,18 +332,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On("umbracoNode.id = latest.nodeId");
|
||||
}
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, propertyEditorAlias FROM cmsPropertyData " +
|
||||
"INNER JOIN umbracoNode ON cmsPropertyData.contentNodeId = umbracoNode.id " +
|
||||
"INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid " +
|
||||
"INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId "+
|
||||
"WHERE umbracoNode.nodeObjectType = '" + Constants.ObjectTypes.Media + "'" + additionWhereStatement + ") as property")
|
||||
.On("umbracoNode.id = property.contentNodeId");
|
||||
}
|
||||
|
||||
return sql;
|
||||
return entitySql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, string additionWhereStatement, Guid nodeObjectType)
|
||||
@@ -298,7 +374,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetGroupBy(bool isContent, bool isMedia)
|
||||
protected virtual Sql GetGroupBy(bool isContent, bool isMedia, bool includeSort = true)
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
@@ -324,19 +400,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
columns.Add("contenttype.thumbnail");
|
||||
columns.Add("contenttype.isContainer");
|
||||
}
|
||||
|
||||
var sql = new Sql()
|
||||
.GroupBy(columns.ToArray());
|
||||
|
||||
if (isMedia)
|
||||
if (includeSort)
|
||||
{
|
||||
columns.Add("property.dataNvarchar");
|
||||
columns.Add("property.propertyEditorAlias");
|
||||
sql = sql.OrderBy("umbracoNode.sortOrder");
|
||||
}
|
||||
|
||||
var sql = new Sql()
|
||||
.GroupBy(columns.ToArray())
|
||||
.OrderBy("umbracoNode.sortOrder");
|
||||
return sql;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -377,15 +452,21 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
[ResultColumn]
|
||||
public List<UmbracoPropertyDto> UmbracoPropertyDtos { get; set; }
|
||||
}
|
||||
|
||||
|
||||
[ExplicitColumns]
|
||||
internal class UmbracoPropertyDto
|
||||
{
|
||||
[Column("propertyEditorAlias")]
|
||||
public string PropertyEditorAlias { get; set; }
|
||||
|
||||
[Column("umbracoFile")]
|
||||
public string UmbracoFile { get; set; }
|
||||
[Column("propertyTypeAlias")]
|
||||
public string PropertyAlias { get; set; }
|
||||
|
||||
[Column("dataNvarchar")]
|
||||
public string NVarcharValue { get; set; }
|
||||
|
||||
[Column("dataNtext")]
|
||||
public string NTextValue { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -412,16 +493,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// Is this the same UmbracoEntity as the current one we're processing
|
||||
if (Current != null && Current.Key == a.uniqueID)
|
||||
{
|
||||
// Yes, just add this UmbracoProperty to the current UmbracoEntity's collection
|
||||
if (Current.UmbracoProperties == null)
|
||||
// Add this UmbracoProperty to the current additional data
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
Current.UmbracoProperties = new List<UmbracoEntity.UmbracoProperty>();
|
||||
}
|
||||
Current.UmbracoProperties.Add(new UmbracoEntity.UmbracoProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.UmbracoFile
|
||||
});
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
|
||||
// Return null to indicate we're not done with this UmbracoEntity yet
|
||||
return null;
|
||||
}
|
||||
@@ -437,14 +517,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Current = _factory.BuildEntityFromDynamic(a);
|
||||
|
||||
//add the property/create the prop list if null
|
||||
Current.UmbracoProperties = new List<UmbracoEntity.UmbracoProperty>
|
||||
{
|
||||
new UmbracoEntity.UmbracoProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.UmbracoFile
|
||||
}
|
||||
};
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
|
||||
// Return the now populated previous UmbracoEntity (or null if first time through)
|
||||
return prev;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
@@ -37,5 +38,26 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update published xml for the content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdateContentXml(IContent content, Func<IContent, XElement> xml);
|
||||
|
||||
/// <summary>
|
||||
/// Used to remove the content xml for a content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
void DeleteContentXml(IContent content);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update preview xml for the content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdatePreviewXml(IContent content, Func<IContent, XElement> xml);
|
||||
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -1,9 +1,15 @@
|
||||
using Umbraco.Core.Models;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IDataTypeDefinitionRepository : IRepositoryQueryable<int, IDataTypeDefinition>
|
||||
{
|
||||
|
||||
PreValueCollection GetPreValuesCollectionByDataTypeId(int dataTypeId);
|
||||
string GetPreValueAsString(int preValueId);
|
||||
|
||||
void AddOrUpdatePreValues(IDataTypeDefinition dataType, IDictionary<string, PreValue> values);
|
||||
void AddOrUpdatePreValues(int dataTypeId, IDictionary<string, PreValue> values);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,25 @@
|
||||
using Umbraco.Core.Models;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IMediaRepository : IRepositoryVersionable<int, IMedia>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update published xml for the media item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdateContentXml(IMedia content, Func<IMedia, XElement> xml);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update preview xml for the content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdatePreviewXml(IMedia content, Func<IMedia, XElement> xml);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
@@ -54,5 +55,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Sql sql, int pageIndex, int pageSize, out int totalRecords,
|
||||
Func<IEnumerable<TDto>, int[]> resolveIds);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update published xml for the media item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdateContentXml(IMember content, Func<IMember, XElement> xml);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update preview xml for the content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdatePreviewXml(IMember content, Func<IMember, XElement> xml);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface ITagsRepository : IRepositoryQueryable<int, ITag>
|
||||
{
|
||||
IEnumerable<TaggedEntity> GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup);
|
||||
|
||||
IEnumerable<TaggedEntity> GetTaggedEntitiesByTag(TaggableObjectTypes objectType, string tag, string tagGroup = null);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all tags for an entity type (content/media/member)
|
||||
/// </summary>
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
|
||||
var languageDto = Database.First<LanguageDto>(sql);
|
||||
var languageDto = Database.FirstOrDefault<LanguageDto>(sql);
|
||||
if (languageDto == null)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -21,6 +22,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
private readonly IMediaTypeRepository _mediaTypeRepository;
|
||||
private readonly ITagsRepository _tagRepository;
|
||||
private readonly ContentXmlRepository<IMedia> _contentXmlRepository;
|
||||
private readonly ContentPreviewRepository<IMedia> _contentPreviewRepository;
|
||||
|
||||
public MediaRepository(IDatabaseUnitOfWork work, IMediaTypeRepository mediaTypeRepository, ITagsRepository tagRepository)
|
||||
: base(work)
|
||||
@@ -29,7 +32,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (tagRepository == null) throw new ArgumentNullException("tagRepository");
|
||||
_mediaTypeRepository = mediaTypeRepository;
|
||||
_tagRepository = tagRepository;
|
||||
|
||||
_contentXmlRepository = new ContentXmlRepository<IMedia>(work, NullCacheProvider.Current);
|
||||
_contentPreviewRepository = new ContentPreviewRepository<IMedia>(work, NullCacheProvider.Current);
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
|
||||
@@ -40,7 +44,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (tagRepository == null) throw new ArgumentNullException("tagRepository");
|
||||
_mediaTypeRepository = mediaTypeRepository;
|
||||
_tagRepository = tagRepository;
|
||||
|
||||
_contentXmlRepository = new ContentXmlRepository<IMedia>(work, NullCacheProvider.Current);
|
||||
_contentPreviewRepository = new ContentPreviewRepository<IMedia>(work, NullCacheProvider.Current);
|
||||
EnsureUniqueNaming = true;
|
||||
}
|
||||
|
||||
@@ -137,12 +142,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"DELETE FROM umbracoRelation WHERE parentId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE childId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsDocument WHERE NodeId = @Id",
|
||||
"DELETE FROM cmsDocument WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsPropertyData WHERE contentNodeId = @Id",
|
||||
"DELETE FROM cmsPreviewXml WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsContentVersion WHERE ContentId = @Id",
|
||||
"DELETE FROM cmsContentXml WHERE nodeID = @Id",
|
||||
"DELETE FROM cmsContent WHERE NodeId = @Id",
|
||||
"DELETE FROM cmsContentXml WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsContent WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
@@ -181,6 +186,22 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return media;
|
||||
}
|
||||
|
||||
public void AddOrUpdateContentXml(IMedia content, Func<IMedia, XElement> xml)
|
||||
{
|
||||
var contentExists = Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @Id", new { Id = content.Id }) != 0;
|
||||
|
||||
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity<IMedia>(contentExists, content, xml));
|
||||
}
|
||||
|
||||
public void AddOrUpdatePreviewXml(IMedia content, Func<IMedia, XElement> xml)
|
||||
{
|
||||
var previewExists =
|
||||
Database.ExecuteScalar<int>("SELECT COUNT(nodeId) FROM cmsPreviewXml WHERE nodeId = @Id AND versionId = @Version",
|
||||
new { Id = content.Id, Version = content.Version }) != 0;
|
||||
|
||||
_contentPreviewRepository.AddOrUpdate(new ContentPreviewEntity<IMedia>(previewExists, content, xml));
|
||||
}
|
||||
|
||||
protected override void PerformDeleteVersion(int id, Guid versionId)
|
||||
{
|
||||
Database.Delete<PreviewXmlDto>("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
|
||||
@@ -299,7 +320,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Database.Update(newContentDto);
|
||||
}
|
||||
|
||||
//In order to update the ContentVersion we need to retreive its primary key id
|
||||
//In order to update the ContentVersion we need to retrieve its primary key id
|
||||
var contentVerDto = Database.SingleOrDefault<ContentVersionDto>("WHERE VersionId = @Version", new { Version = entity.Version });
|
||||
dto.Id = contentVerDto.Id;
|
||||
//Updates the current version - cmsContentVersion
|
||||
@@ -403,4 +424,4 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return currentName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"DELETE FROM cmsContentType2ContentType WHERE childContentTypeId = @Id",
|
||||
"DELETE FROM cmsPropertyType WHERE contentTypeId = @Id",
|
||||
"DELETE FROM cmsPropertyTypeGroup WHERE contenttypeNodeId = @Id",
|
||||
"DELETE FROM cmsContentType WHERE NodeId = @Id",
|
||||
"DELETE FROM cmsContentType WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user