Compare commits
409 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bc33e0115 | |||
| 8576d9c67e | |||
| 9452d5fd09 | |||
| 1f40d726de | |||
| 2699611ba3 | |||
| b1fa06bfe8 | |||
| 4dc22b6ce4 | |||
| 883277125a | |||
| ff961abaab | |||
| b2414c1ab8 | |||
| 0e392b398c | |||
| 5914690ad8 | |||
| dbbdd16bb9 | |||
| 762cca145f | |||
| 5cd2d568e3 | |||
| 259fbcb8f0 | |||
| db3f21429e | |||
| 04b9607741 | |||
| 5bd2571395 | |||
| c0cd157e60 | |||
| ac2f9b172c | |||
| b8e4a73c3b | |||
| 68c4255a51 | |||
| d07212c89b | |||
| 28c55320a1 | |||
| fd58017e97 | |||
| 09408b898e | |||
| d1b05332c5 | |||
| caad0afed8 | |||
| 62d365573f | |||
| f3b7a8a581 | |||
| a765f36d24 | |||
| 046da1a8ce | |||
| ca7abd6c78 | |||
| 7cc0f2a514 | |||
| 4882df43bd | |||
| ee2943b9fb | |||
| c250fa560e | |||
| b017e8690a | |||
| 8a9680e75c | |||
| 36c66e676a | |||
| ba530061a0 | |||
| 89ae3bc143 | |||
| 3951f59d09 | |||
| cd8c998ebf | |||
| 2cb544591b | |||
| 1b1b5c047c | |||
| fa5b9e5689 | |||
| c26df8da6f | |||
| 1e02d85fca | |||
| d1dc2331f8 | |||
| d503deb8c5 | |||
| 0859b92aaf | |||
| 695d26434c | |||
| a19de645e4 | |||
| de9a27db10 | |||
| b6d5b7d603 | |||
| 93d7cf4dc3 | |||
| 0c42596dc8 | |||
| 8cf9c1ba97 | |||
| 7a47d63b48 | |||
| 4648a8c103 | |||
| 87947871d1 | |||
| 87fee572ff | |||
| 89f7a3ec63 | |||
| 7092a9ccbb | |||
| e9ea9b5e1b | |||
| fd1efb29ec | |||
| cf4781153e | |||
| ebed142cd5 | |||
| d162aba14a | |||
| ec075f5807 | |||
| dca90e6316 | |||
| df31fafec5 | |||
| 828dc64035 | |||
| 0b74164a8e | |||
| 62be1b1267 | |||
| 85ae7e764f | |||
| 3daa624627 | |||
| d8af1aaf7b | |||
| f2d105d8b9 | |||
| 5b0a8c0668 | |||
| c3ccf3a609 | |||
| 60bbede408 | |||
| 1d0299af89 | |||
| c2d0e255df | |||
| 005d3e7d64 | |||
| 12f8638223 | |||
| e3f9e8c842 | |||
| a475f72d50 | |||
| a559ef9f90 | |||
| be83302b14 | |||
| 83d7ea9ef1 | |||
| 95024442de | |||
| 69f54b5f22 | |||
| 3404f95b2e | |||
| e56738481b | |||
| cb59dc353b | |||
| d1b75eac08 | |||
| 8fabd4e4ed | |||
| 564d92bed7 | |||
| 95f103ccc2 | |||
| 0ace2fdae7 | |||
| 5da3541584 | |||
| ef86d2f1f1 | |||
| a10a6d1af8 | |||
| 6d87174cc1 | |||
| 9af9c3fe77 | |||
| 9cedf5da4c | |||
| 906d675dca | |||
| f1b3105202 | |||
| 3ebb213916 | |||
| a65ca205de | |||
| 3e1120612b | |||
| 8d06d39a62 | |||
| da7fea47c6 | |||
| f2442b25f6 | |||
| 300d3ff09b | |||
| e6337b8f14 | |||
| 2be785ace3 | |||
| 5e2d991fab | |||
| 536cb4caf1 | |||
| 27745ea141 | |||
| 5289c55740 | |||
| 791773fc8a | |||
| 1da27e6c2b | |||
| a909b7904e | |||
| 1b1abce7da | |||
| fbc10be381 | |||
| 61f2647b62 | |||
| a5bea7fc59 | |||
| b9be5c2561 | |||
| 97556de447 | |||
| d5bde0d8df | |||
| cc5ca0b5fe | |||
| 0cb9cc6840 | |||
| d38d7b1ff4 | |||
| 2d87f933d5 | |||
| a734a0cff7 | |||
| d0ace55d03 | |||
| 3fda0308ac | |||
| d796b2afc1 | |||
| f95cfc2ee0 | |||
| c5d1439422 | |||
| 5e9f4559b6 | |||
| 4bbb0441a6 | |||
| 4cf1d7d9a4 | |||
| a6a3ddca75 | |||
| 27cfa85d3a | |||
| a9e1e7b634 | |||
| 9f5f920c81 | |||
| f9a0d91299 | |||
| 82c2560822 | |||
| f467b8cb6c | |||
| aea1a03453 | |||
| 1568e5f19c | |||
| 8dff47db78 | |||
| 987e48733a | |||
| ac5142443a | |||
| 44360d83aa | |||
| 021cb817d4 | |||
| f4f91fba78 | |||
| dec5e8ad6c | |||
| a6b2196c10 | |||
| 4321c8d24e | |||
| 4cff3a3c28 | |||
| 5458c9a310 | |||
| 0045ec353f | |||
| 716d3e95f1 | |||
| beeb28f390 | |||
| 080e8816a5 | |||
| f7eb323bd5 | |||
| 0f484fdf49 | |||
| d779422bf4 | |||
| 11ea698969 | |||
| 0e0e6b5c41 | |||
| 4c218621c6 | |||
| c150a91e50 | |||
| 7be9a0a987 | |||
| 50589c0911 | |||
| e61ae618e8 | |||
| 930e6a0989 | |||
| 7c50b32684 | |||
| 0f7daf7ebd | |||
| 12cbc2a9c5 | |||
| 959d263619 | |||
| 6a1fb52b25 | |||
| 18cd043421 | |||
| ddb2f82aba | |||
| 6c99e7951f | |||
| e44e745761 | |||
| 30c11439e4 | |||
| 0883f621f6 | |||
| 2d0784d1e5 | |||
| af0011f32a | |||
| ab6c5ac21a | |||
| 227a38fb98 | |||
| 06f9dee649 | |||
| 75680192bb | |||
| a53efb394f | |||
| 98ed32c8cf | |||
| df10ebebca | |||
| 88dc73cd66 | |||
| cd0919aeeb | |||
| ce6711b587 | |||
| 6cb3fcf9ad | |||
| e5878554bd | |||
| 44c8c4b5b8 | |||
| c0b5525dd7 | |||
| 36f8a8e1dd | |||
| 16f73b56ab | |||
| 47dc2e6214 | |||
| c6483f0380 | |||
| 168b38b2a3 | |||
| 70ca4ac913 | |||
| 72099192b5 | |||
| ea48128869 | |||
| f0b22146c8 | |||
| fe0d94687a | |||
| 238c3d38e8 | |||
| 6af4f1f2c6 | |||
| e215fb056f | |||
| e6178efcfb | |||
| 30cf0e2040 | |||
| 48d620cdb0 | |||
| 3bd487d092 | |||
| 6c8c37256b | |||
| 37b1fcbaf0 | |||
| dc111768e3 | |||
| 6589d5d5d3 | |||
| e6975a71d5 | |||
| 33b497e5f4 | |||
| c5e7c81c19 | |||
| 47d1fe7082 | |||
| 735bd574ff | |||
| 5c0d9785e0 | |||
| db14868324 | |||
| 06952833ef | |||
| 2a90e93a6f | |||
| 0d94ddb96e | |||
| c7645b55ba | |||
| 208806c027 | |||
| 8024610364 | |||
| 8e4644568b | |||
| e0a71830fa | |||
| 5b0057c258 | |||
| fb61c55fa7 | |||
| a70ef52964 | |||
| 51204ee401 | |||
| 657f165ffb | |||
| 3bd98d851a | |||
| 9eea46b19b | |||
| 76fb5d260f | |||
| 267cd46ea0 | |||
| 96f6a0161f | |||
| 7bc53adc67 | |||
| 8ecff73c18 | |||
| 35e65ad18c | |||
| 8def8eaa86 | |||
| c0774ad9b9 | |||
| f306cbe457 | |||
| 577b989c4c | |||
| e6b162f4f6 | |||
| b40cc1879f | |||
| 8a7c7bf77d | |||
| 38a1179de5 | |||
| f263b4d92b | |||
| c612727116 | |||
| ab9c9df7d6 | |||
| c607e50433 | |||
| df5555bdf1 | |||
| 9506339e6f | |||
| 68605a7560 | |||
| 839dd7315a | |||
| f1314628d7 | |||
| e23ed30b0c | |||
| 55cb46927e | |||
| 654c3b7403 | |||
| 4195754b0c | |||
| 96a6f17bd7 | |||
| 61d99c4061 | |||
| 0a6e91a2f9 | |||
| cf9e786e45 | |||
| ba1d3fd3e6 | |||
| ac01fd48fa | |||
| f53fb694be | |||
| 1ecd8fa87d | |||
| ce1c9d697b | |||
| c67a76fb03 | |||
| 3d72a4497c | |||
| 30cc8e0861 | |||
| 30ca3f6df9 | |||
| cccfed6efe | |||
| 82c148e997 | |||
| c50a3e7a27 | |||
| 811cbe2339 | |||
| a8bf881ae1 | |||
| c446be734c | |||
| f0f7f6af55 | |||
| 19bd8ae193 | |||
| 81d8f74e0d | |||
| 0011d568c6 | |||
| 159718bf4f | |||
| b9ff3ca729 | |||
| 4f3ac36d7f | |||
| a9257ad366 | |||
| 2218459877 | |||
| 8f5e2946d6 | |||
| 19c3b251a0 | |||
| ce4c855f00 | |||
| 48c45447e4 | |||
| 4683144987 | |||
| 238a237cb5 | |||
| cde1ca9f83 | |||
| 93e2d8d822 | |||
| 8609389bdb | |||
| 48f985b70a | |||
| b02afb3af8 | |||
| b9d814c3fb | |||
| 1b54ce1d48 | |||
| e3efc0d19b | |||
| 3ba9e09164 | |||
| d148c10c66 | |||
| 2b573b9070 | |||
| 4cb03ab36c | |||
| 3ebbcc77e9 | |||
| 8be97295dc | |||
| 3dd411f159 | |||
| 8b141dc51a | |||
| 278aa3f820 | |||
| a7a38478db | |||
| b2e004b825 | |||
| 10df6e878c | |||
| eac11c1b80 | |||
| 0ad5da67ea | |||
| 3fb9ffca5b | |||
| 8e7fe5ee55 | |||
| 9554c6a1c6 | |||
| 8597876c92 | |||
| 3df7d81bde | |||
| f82ae4fdda | |||
| 4a981225b3 | |||
| 0cd115c268 | |||
| 291b0582e4 | |||
| f4e48872a2 | |||
| 9e320700e2 | |||
| 7f0ff70ca9 | |||
| 65e3b7f951 | |||
| 156f145c69 | |||
| a0c941dac2 | |||
| 33eb9d40f3 | |||
| cf8186653c | |||
| 75403d3b94 | |||
| 083bab0528 | |||
| ee3e3787a8 | |||
| a3895ab149 | |||
| c590c6a265 | |||
| 6c1bf4b85f | |||
| 3632d6b0c6 | |||
| bf95792524 | |||
| 885b421201 | |||
| b11143e2c4 | |||
| 0df1ebb83e | |||
| 204d7a79aa | |||
| e68629b8bc | |||
| 84858bea65 | |||
| 243633365e | |||
| dc7e18b97b | |||
| d3c553c945 | |||
| 05fc15d164 | |||
| a71961c35b | |||
| da8af696c5 | |||
| 12f5df33da | |||
| f184276ef8 | |||
| c72ab927a6 | |||
| 7bc2375a77 | |||
| 392fbb836f | |||
| 0cb8603c80 | |||
| 20fc02053a | |||
| e389dc39a7 | |||
| fbd4669da8 | |||
| c138c6643a | |||
| a2b876608f | |||
| c95c1a7038 | |||
| 9e1c5e71e4 | |||
| aba68720bb | |||
| 1b1722c875 | |||
| 248af2eaa2 | |||
| 0709174560 | |||
| b0c0ed050d | |||
| e3a085774c | |||
| 6f0ddc37a0 | |||
| d3eb5ceabe | |||
| 1bffb7395c | |||
| e636a42744 | |||
| d3927a1265 | |||
| d6fc106588 | |||
| 68fc833280 | |||
| 5a8443fe72 | |||
| 153fb4a248 | |||
| 72ef5b01d2 | |||
| 0854fee4ee | |||
| e122d40fb9 | |||
| b696aa4340 | |||
| e32dd303e3 | |||
| 7c524abb84 | |||
| 993bac8a29 | |||
| 51769847ad | |||
| 918e7ad682 |
@@ -2,7 +2,6 @@
|
||||
syntax: glob
|
||||
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.user
|
||||
*.aps
|
||||
@@ -36,6 +35,9 @@ src\Umbraco.Web.UI\media\*
|
||||
src\Umbraco.Web.UI\masterpages\*
|
||||
src\Umbraco.Web.UI\macroScripts\*
|
||||
src\Umbraco.Web.UI\xslt\*
|
||||
src\Umbraco.Web.UI\images\*
|
||||
src\Umbraco.Web.UI\scripts\*
|
||||
src\Umbraco.Web.UI\Web.*.config.transformed
|
||||
|
||||
umbraco\presentation\umbraco\plugins\uComponents\uComponentsInstaller.ascx
|
||||
umbraco\presentation\packages\uComponents\MultiNodePicker\CustomTreeService.asmx
|
||||
@@ -56,4 +58,6 @@ src/Umbraco.Tests/config/umbracoSettings.config
|
||||
src/Umbraco.Web.UI/App_Plugins/*
|
||||
src/Umbraco.Web.UI/Views/*
|
||||
|
||||
src\Umbraco.Web.UI\[W]eb.config
|
||||
src\Umbraco.Web.UI\[W]eb.config
|
||||
src/packages/
|
||||
build/*.zip
|
||||
|
||||
@@ -10,7 +10,20 @@ d03fcffb8834a9583a56813bb44b6abbd9f042cc Release-4.6.0
|
||||
096f20bb0575d6199f20fcb3147b63554e765a74 Release-4.8.0
|
||||
8f8a203857886b373148af29edd57460a42940be Release-4.8.1
|
||||
de73e687ddf6086ed52b6554676c1632865d07f2 Release-4.9.0
|
||||
de73e687ddf6086ed52b6554676c1632865d07f2 Release-4.9.0
|
||||
0000000000000000000000000000000000000000 Release-4.9.0
|
||||
0000000000000000000000000000000000000000 Release-4.9.0
|
||||
09f5a69cf19ebf7ddd9501e5258bee1e6a125391 Release-4.9.0
|
||||
8d7d8609e2e4b971da99cd97f72132ce85ce3333 Release-4.9.1
|
||||
f6da531fbb4c251ff61d314e2a7effb13c71e74a Release-4.10.0
|
||||
20e4dff821d8ac2527a5353618fa1a23ea1d8b34 Release-4.11.0
|
||||
7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
|
||||
7f827760cb49d749616859f528d19dde64807947 Release-4.11.1
|
||||
6eb5f2fb5a88aa29ea544499df9160a1b31b5638 Release-4.11.1
|
||||
73711b806a4044dbf0d7d7c095ddfdda23b09932 4.11.2
|
||||
73711b806a4044dbf0d7d7c095ddfdda23b09932 4.11.2
|
||||
0000000000000000000000000000000000000000 4.11.2
|
||||
73711b806a4044dbf0d7d7c095ddfdda23b09932 Release-4.11.2
|
||||
77db220b89e166b3c0736ed321ecfd6416cddbcd Release-4.11.2.1
|
||||
54cde33b809dcb3a1f7e7ae0d5375f6dd0d89c8d Release-4.11.2.2
|
||||
baa44b79cf90a60631e38e11f771c200b08a4583 Release-4.11.3
|
||||
e4d0c7e740555d8707ba71f55a623a3f96da8e65 Release-4.11.3.1
|
||||
e4d0c7e740555d8707ba71f55a623a3f96da8e65 Release-4.11.3.1
|
||||
0000000000000000000000000000000000000000 Release-4.11.3.1
|
||||
e02f5aebb87e3f07d27376647756caa9762931d8 Release-4.11.4
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
NuGet.exe pack NuSpecs\UmbracoCms.Core.nuspec
|
||||
NuGet.exe pack NuSpecs\UmbracoCms.nuspec
|
||||
REM pause
|
||||
+17
-1
@@ -1,5 +1,21 @@
|
||||
@ECHO OFF
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj"
|
||||
set version=4.11.6
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%version%
|
||||
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Code\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Data\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Plugins\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\css\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\macroScripts\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\masterpages\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\media\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\scripts\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\usercontrols\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\xslt\dummy.txt
|
||||
|
||||
NuGet.exe pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
|
||||
NuGet.exe pack NuSpecs\UmbracoCms.nuspec -Version %version%
|
||||
|
||||
|
||||
if ERRORLEVEL 1 goto :showerror
|
||||
|
||||
|
||||
+11
-1
@@ -24,6 +24,9 @@
|
||||
<PropertyGroup Condition="'$(BUILD_NUMBER)'!=''">
|
||||
<DECIMAL_BUILD_NUMBER>.$(BUILD_NUMBER)</DECIMAL_BUILD_NUMBER>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(BUILD_RELEASE)'!=''">
|
||||
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)</DECIMAL_BUILD_NUMBER>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BuildConfiguration>Release</BuildConfiguration>
|
||||
@@ -160,7 +163,7 @@
|
||||
<Message Text="Finished offsetting timestamps" Importance="high" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CompileProjects">
|
||||
<Target Name="CompileProjects" DependsOnTargets="SetVersionNumber">
|
||||
|
||||
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
|
||||
<!-- For UseWPP_CopyWebApplication=True see http://stackoverflow.com/questions/1983575/copywebapplication-with-web-config-transformations -->
|
||||
@@ -232,6 +235,13 @@
|
||||
<Message Text="Finished compiling projects" Importance="high" />
|
||||
</Target>
|
||||
|
||||
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
|
||||
<!-- Match & replace 3 and 4 digit version numbers and -beta (if it's there) -->
|
||||
<FileUpdate Files="..\src\Umbraco.Core\Configuration\GlobalSettings.cs"
|
||||
Regex="(\d+)\.(\d+)\.(\d+)(.(\d+))?(-([a-zA-Z]+))?"
|
||||
ReplacementText="$(BUILD_RELEASE)"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="AfterBuild">
|
||||
<Message Text="Hi" />
|
||||
</Target>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>4.10.0</version>
|
||||
<version>$version$</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Morten Christensen</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
@@ -26,6 +26,7 @@
|
||||
<file src="..\_BuildOutput\WebApp\bin\ICSharpCode.SharpZipLib.dll" target="lib\ICSharpCode.SharpZipLib.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\interfaces.dll" target="lib\interfaces.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Lucene.Net.dll" target="lib\Lucene.Net.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\log4net.dll" target="lib\log4net.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.Web.Helpers.dll" target="lib\Microsoft.Web.Helpers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.Web.Infrastructure.dll" target="lib\Microsoft.Web.Infrastructure.dll" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoCms</id>
|
||||
<version>4.10.0</version>
|
||||
<version>$version$</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Morten Christensen</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
@@ -15,7 +15,7 @@
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="4.9.0" />
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
@@ -27,16 +27,19 @@
|
||||
<file src="..\_BuildOutput\WebApp\scripts\**" target="Content\scripts" />
|
||||
<file src="..\_BuildOutput\WebApp\usercontrols\**" target="Content\usercontrols" />
|
||||
<file src="..\_BuildOutput\WebApp\xslt\**" target="Content\xslt" />
|
||||
<file src="..\_BuildOutput\WebApp\Views\**" target="Content\Views" />
|
||||
<file src="..\_BuildOutput\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="..\_BuildOutput\WebApp\Web.config" target="Content\Web.config" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Code\**" target="UmbracoFiles\App_Code" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Data\**" target="UmbracoFiles\App_Data" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
|
||||
<file src="..\_BuildOutput\WebApp\config\**" target="UmbracoFiles\config" />
|
||||
<file src="..\_BuildOutput\WebApp\install\**" target="UmbracoFiles\install" />
|
||||
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
|
||||
<file src="..\_BuildOutput\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="..\_BuildOutput\WebApp\Global.asax" target="UmbracoFiles\Global.asax" />
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
</files>
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
@ECHO OFF
|
||||
|
||||
:choice
|
||||
set /P c=WARNING! Are you sure you want to continue, this will remove all package files, view files, sqlce database, etc... Press 'Y' to auto-remove all files/folders, 'N' to cancel or 'C' to prompt for each folder removal?
|
||||
if /I "%c%" EQU "C" goto :prompt
|
||||
if /I "%c%" EQU "Y" goto :auto
|
||||
if /I "%c%" EQU "N" goto :exit
|
||||
goto :choice
|
||||
|
||||
|
||||
:prompt
|
||||
|
||||
echo Current folder: %CD%
|
||||
|
||||
echo Removing sqlce database
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
|
||||
|
||||
echo Resetting installedPackages.config
|
||||
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
|
||||
|
||||
echo Removing plugin cache files
|
||||
del ..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*
|
||||
|
||||
echo Removing cache files and examine index
|
||||
del ..\src\Umbraco.Web.UI\App_Data\TEMP\*.*
|
||||
|
||||
echo Removing log files
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Logs\*.*
|
||||
|
||||
echo Removing packages
|
||||
del ..\src\Umbraco.Web.UI\App_Data\packages\*.*
|
||||
|
||||
echo Removing previews
|
||||
del ..\src\Umbraco.Web.UI\App_Data\preview\*.*
|
||||
|
||||
echo Removing app code files (typically added by starterkits)
|
||||
del ..\src\Umbraco.Web.UI\App_Code\*.*
|
||||
|
||||
echo Removing xslt files
|
||||
del ..\src\Umbraco.Web.UI\xslt\*.*
|
||||
|
||||
echo Removing user control files
|
||||
del ..\src\Umbraco.Web.UI\UserControls\*.*
|
||||
|
||||
echo Removing masterpage files
|
||||
del ..\src\Umbraco.Web.UI\masterpages\*.*
|
||||
|
||||
echo Removing view files
|
||||
del ..\src\Umbraco.Web.UI\Views\*.*
|
||||
|
||||
echo Removing razor files
|
||||
del ..\src\Umbraco.Web.UI\macroScripts\*.*
|
||||
|
||||
echo Removing media files
|
||||
del ..\src\Umbraco.Web.UI\media\*.*
|
||||
|
||||
echo Removing script files
|
||||
del ..\src\Umbraco.Web.UI\scripts\*.*
|
||||
|
||||
echo Removing css files
|
||||
del ..\src\Umbraco.Web.UI\css\*.*
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
|
||||
:auto
|
||||
|
||||
echo Current folder: %CD%
|
||||
|
||||
echo Removing sqlce database
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
|
||||
|
||||
echo Resetting installedPackages.config
|
||||
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
|
||||
|
||||
echo Removing plugin cache files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*) DO DEL %%A
|
||||
|
||||
echo Removing cache files and examine index
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\*.*) DO DEL %%A
|
||||
|
||||
echo Removing log files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\Logs\*.*) DO DEL %%A
|
||||
|
||||
echo Removing packages
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\packages\*.*) DO DEL %%A
|
||||
|
||||
echo Removing previews
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\preview\*.*) DO DEL %%A
|
||||
|
||||
echo Removing app code files (typically added by starterkits)
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Code\*.*) DO DEL %%A
|
||||
|
||||
echo Removing xslt files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\xslt\*.*) DO DEL %%A
|
||||
|
||||
echo Removing masterpage files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\masterpages\*.*) DO DEL %%A
|
||||
|
||||
echo Removing user control files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\usercontrols\*.*) DO DEL %%A
|
||||
|
||||
echo Removing view files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\*.*) DO DEL %%A
|
||||
|
||||
echo Removing razor files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\macroScripts\*.*) DO DEL %%A
|
||||
|
||||
echo Removing media files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\media\*.*) DO DEL %%A
|
||||
|
||||
echo Removing script files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\scripts\*.*) DO DEL %%A
|
||||
|
||||
echo Removing css files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\css\*.*) DO DEL %%A
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
|
||||
:exit
|
||||
exit
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<solution>
|
||||
<add key="disableSourceControlIntegration" value="true" />
|
||||
</solution>
|
||||
</configuration>
|
||||
Binary file not shown.
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
|
||||
|
||||
<!-- Determines if package restore consent is required to restore packages -->
|
||||
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
|
||||
|
||||
<!-- Download NuGet.exe if it does not already exist -->
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default will used the registered sources under %APPDATA%\NuGet\NuGet.Config -->
|
||||
<!--
|
||||
<PackageSource Include="https://nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
-->
|
||||
<PackageSource Include="https://nuget.org/api/v2/" />
|
||||
<PackageSource Include="http://www.myget.org/F/umbracocore/" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
|
||||
<PackagesConfig>packages.config</PackagesConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\nuget.exe</NuGetExePath>
|
||||
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
|
||||
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
|
||||
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<ResolveReferencesDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(ResolveReferencesDependsOn);
|
||||
</ResolveReferencesDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
$(BuildDependsOn);
|
||||
BuildPackage;
|
||||
</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<SetEnvironmentVariable EnvKey="VisualStudioVersion" EnvValue="$(VisualStudioVersion)" Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' " />
|
||||
<!--
|
||||
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
parallel builds will have to wait for it to complete.
|
||||
-->
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_DownloadNuGet">
|
||||
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(BuildCommand)"
|
||||
Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
|
||||
<Exec Command="$(BuildCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<OutputFilename ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.Core" />
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Net" />
|
||||
<Using Namespace="Microsoft.Build.Framework" />
|
||||
<Using Namespace="Microsoft.Build.Utilities" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
OutputFilename = Path.GetFullPath(OutputFilename);
|
||||
|
||||
Log.LogMessage("Downloading latest version of NuGet.exe...");
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<EnvKey ParameterType="System.String" Required="true" />
|
||||
<EnvValue ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
||||
@@ -9,14 +9,14 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// A resolver to return all IAction objects
|
||||
/// </summary>
|
||||
internal sealed class ActionsResolver : ManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
internal sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="packageActions"></param>
|
||||
internal ActionsResolver(IEnumerable<Type> packageActions)
|
||||
internal ActionsResolver(Func<IEnumerable<Type>> packageActions)
|
||||
: base(packageActions)
|
||||
{
|
||||
|
||||
@@ -34,9 +34,9 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
protected override IEnumerable<IAction> CreateInstances()
|
||||
{
|
||||
{
|
||||
var actions = new List<IAction>();
|
||||
var foundIActions = PluginManager.Current.ResolveActions();
|
||||
var foundIActions = InstanceTypes;
|
||||
foreach (var type in foundIActions)
|
||||
{
|
||||
IAction typeInstance;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Umbraco.Core
|
||||
/// <remarks>
|
||||
/// Any caching that is done in the application (app wide) should be done through this property
|
||||
/// </remarks>
|
||||
internal CacheHelper ApplicationCache { get; private set; }
|
||||
public CacheHelper ApplicationCache { get; private set; }
|
||||
|
||||
// IsReady is set to true by the boot manager once it has successfully booted
|
||||
// note - the original umbraco module checks on content.Instance in umbraco.dll
|
||||
@@ -111,6 +111,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string ConfigurationStatus
|
||||
{
|
||||
get
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core
|
||||
/// <remarks>
|
||||
/// This class may be opened publicly at some point but needs a review of what is absoletely necessary.
|
||||
/// </remarks>
|
||||
internal class CacheHelper
|
||||
public class CacheHelper
|
||||
{
|
||||
private readonly Cache _cache;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Core
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="refreshers"></param>
|
||||
internal CacheRefreshersResolver(IEnumerable<Type> refreshers)
|
||||
internal CacheRefreshersResolver(Func<IEnumerable<Type>> refreshers)
|
||||
: base(refreshers)
|
||||
{
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An attribute used to decorate classes or methods that have been marked to be obsoleted
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This attribute exists because sometimes we may not want to explicitly [Obsolete] a class or method because we
|
||||
/// know it is still in use and we don't want warning messages showing up in developers output windows when they compile, however
|
||||
/// we will be able to produce reports declaring which classes/methods/etc... have been marked for being obsoleted in the near future
|
||||
/// </remarks>
|
||||
internal class UmbracoDeprecateAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor requries a description
|
||||
/// </summary>
|
||||
/// <param name="description"></param>
|
||||
public UmbracoDeprecateAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,30 @@ using System;
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute used to decorate classes or methods that have been marked to become public but require more testing and review
|
||||
/// before this is possible.
|
||||
/// Marks the program elements that Umbraco is experimenting with and could become public.
|
||||
/// </summary>
|
||||
internal class UmbracoExperimentalFeatureAttribute : Attribute
|
||||
/// <remarks>
|
||||
/// <para>Indicates that Umbraco is experimenting with code that potentially could become
|
||||
/// public, but we're not sure, and the code is not stable and can be refactored at any time.</para>
|
||||
/// <para>The issue tracker should contain more details, discussion, and planning.</para>
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
internal sealed class UmbracoExperimentalFeatureAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// constructor requires a tracker url and a description
|
||||
/// Initializes a new instance of the <see cref="UmbracoExperimentalFeatureAttribute"/> class with a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoExperimentalFeatureAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoExperimentalFeatureAttribute"/> class with a tracker url and a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoExperimentalFeatureAttribute(string trackerUrl, string description)
|
||||
{
|
||||
|
||||
|
||||
@@ -3,20 +3,31 @@ using System;
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute used to decorate classes or methods that have potential to become part of the public API
|
||||
/// Marks the program elements that Umbraco is considering making public.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Classes, properties or methods marked with this attribute will have a tracker URL assigned where discussions may take place
|
||||
/// regarding whether or not this should become part of the public APIs and if/when. Please note that any objects marked with this
|
||||
/// attribute may not ever become public, this attribute exists to tag code that has potential to become public pending reviews.
|
||||
/// <para>Indicates that Umbraco considers making the (currently internal) program element public
|
||||
/// at some point in the future, but the decision is not fully made yet and is still pending reviews.</para>
|
||||
/// <para>Note that it is not a commitment to make the program element public. It may not ever become public.</para>
|
||||
/// <para>The issue tracker should contain more details, discussion, and planning.</para>
|
||||
/// </remarks>
|
||||
internal class UmbracoProposedPublicAttribute : Attribute
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple=false, Inherited=false)]
|
||||
internal sealed class UmbracoProposedPublicAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// constructor requires a tracker url and a description
|
||||
/// Initializes a new instance of the <see cref="UmbracoProposedPublicAttribute"/> class with a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoProposedPublicAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoProposedPublicAttribute"/> class with a tracker url and a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoProposedPublicAttribute(string trackerUrl, string description)
|
||||
{
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the program elements that Umbraco will obsolete.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Indicates that Umbraco will obsolete the program element at some point in the future, but we do not want to
|
||||
/// explicitely mark it [Obsolete] yet to avoid warning messages showing when developers compile Umbraco.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
internal sealed class UmbracoWillObsoleteAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoWillObsoleteAttribute"/> class with a description.
|
||||
/// </summary>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoWillObsoleteAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoWillObsoleteAttribute"/> class with a tracker url and a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoWillObsoleteAttribute(string trackerUrl, string description)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Routing;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -27,14 +28,31 @@ namespace Umbraco.Core.Configuration
|
||||
#region Private static fields
|
||||
|
||||
// CURRENT UMBRACO VERSION ID
|
||||
private const string CurrentUmbracoVersion = "4.10.0";
|
||||
private const string CurrentUmbracoVersion = "4.11.6";
|
||||
|
||||
private static string _reservedUrlsCache;
|
||||
private static readonly object Locker = new object();
|
||||
//make this volatile so that we can ensure thread safety with a double check lock
|
||||
private static volatile string _reservedUrlsCache;
|
||||
private static string _reservedPathsCache;
|
||||
private static StartsWithContainer _reservedList = new StartsWithContainer();
|
||||
private static string _reservedPaths;
|
||||
private static string _reservedUrls;
|
||||
//ensure the built on (non-changeable) reserved paths are there at all times
|
||||
private const string StaticReservedPaths = "~/app_plugins/,~/install/,";
|
||||
private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,";
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// used for unit tests
|
||||
/// </summary>
|
||||
internal static void ResetCache()
|
||||
{
|
||||
_reservedUrlsCache = null;
|
||||
_reservedPaths = null;
|
||||
_reservedUrls = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reserved urls from web.config.
|
||||
/// </summary>
|
||||
@@ -42,11 +60,19 @@ namespace Umbraco.Core.Configuration
|
||||
public static string ReservedUrls
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls")
|
||||
? ConfigurationManager.AppSettings["umbracoReservedUrls"]
|
||||
: string.Empty;
|
||||
{
|
||||
if (_reservedUrls == null)
|
||||
{
|
||||
var urls = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls")
|
||||
? ConfigurationManager.AppSettings["umbracoReservedUrls"]
|
||||
: string.Empty;
|
||||
|
||||
//ensure the built on (non-changeable) reserved paths are there at all times
|
||||
_reservedUrls = StaticReservedUrls + urls;
|
||||
}
|
||||
return _reservedUrls;
|
||||
}
|
||||
internal set { _reservedUrls = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -57,10 +83,25 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConfigurationManager.AppSettings.ContainsKey("umbracoReservedPaths")
|
||||
? ConfigurationManager.AppSettings["umbracoReservedPaths"]
|
||||
: string.Empty;
|
||||
if (_reservedPaths == null)
|
||||
{
|
||||
var reservedPaths = StaticReservedPaths;
|
||||
//always add the umbraco path to the list
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoPath")
|
||||
&& !ConfigurationManager.AppSettings["umbracoPath"].IsNullOrWhiteSpace())
|
||||
{
|
||||
reservedPaths += ConfigurationManager.AppSettings["umbracoPath"].EnsureEndsWith(',');
|
||||
}
|
||||
|
||||
var allPaths = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedPaths")
|
||||
? ConfigurationManager.AppSettings["umbracoReservedPaths"]
|
||||
: string.Empty;
|
||||
|
||||
_reservedPaths = reservedPaths + allPaths;
|
||||
}
|
||||
return _reservedPaths;
|
||||
}
|
||||
internal set { _reservedPaths = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,6 +156,9 @@ namespace Umbraco.Core.Configuration
|
||||
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
|
||||
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
|
||||
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
|
||||
///
|
||||
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
|
||||
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
|
||||
/// </remarks>
|
||||
internal static string UmbracoMvcArea
|
||||
{
|
||||
@@ -124,7 +168,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified");
|
||||
}
|
||||
return Path.TrimStart('~').TrimStart('/').Replace('/', '-').Trim();
|
||||
return Path.TrimStart(SystemDirectories.Root).TrimStart('~').TrimStart('/').Replace('/', '-').Trim().ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +224,7 @@ namespace Umbraco.Core.Configuration
|
||||
SaveSetting("umbracoConfigurationStatus", value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves a setting into the configuration file.
|
||||
/// </summary>
|
||||
@@ -190,16 +234,16 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
var webConfig = new WebConfigurationFileMap();
|
||||
var vDirs = webConfig.VirtualDirectories;
|
||||
var vDir = FullpathToRoot;
|
||||
var physicalPathToRoot = FullpathToRoot;
|
||||
foreach (VirtualDirectoryMapping v in webConfig.VirtualDirectories)
|
||||
{
|
||||
if (v.IsAppRoot)
|
||||
{
|
||||
vDir = v.PhysicalDirectory;
|
||||
physicalPathToRoot = v.PhysicalDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
string fileName = String.Concat(vDir, "web.config");
|
||||
string fileName = System.IO.Path.Combine(physicalPathToRoot, "web.config");
|
||||
var xml = XDocument.Load(fileName);
|
||||
var appSettings = xml.Root.Descendants("appSettings").Single();
|
||||
|
||||
@@ -220,7 +264,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <value>The fullpath to root.</value>
|
||||
public static string FullpathToRoot
|
||||
{
|
||||
get { return HttpRuntime.AppDomainAppPath; }
|
||||
get { return IOHelper.GetRootDirectorySafe(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -549,7 +593,29 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Determines whether the current request is reserved based on the route table and
|
||||
/// whether the specified URL is reserved or is inside a reserved path.
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <param name="routes">The route collection to lookup the request in</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsReservedPathOrUrl(string url, HttpContextBase httpContext, RouteCollection routes)
|
||||
{
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
if (routes == null) throw new ArgumentNullException("routes");
|
||||
|
||||
//check if the current request matches a route, if so then it is reserved.
|
||||
var route = routes.GetRouteData(httpContext);
|
||||
if (route != null)
|
||||
return true;
|
||||
|
||||
//continue with the standard ignore routine
|
||||
return IsReservedPathOrUrl(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified URL is reserved or is inside a reserved path.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to check.</param>
|
||||
@@ -557,39 +623,43 @@ namespace Umbraco.Core.Configuration
|
||||
/// <c>true</c> if the specified URL is reserved; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsReservedPathOrUrl(string url)
|
||||
{
|
||||
// check if GlobalSettings.ReservedPaths and GlobalSettings.ReservedUrls are unchanged
|
||||
if (!object.ReferenceEquals(_reservedPathsCache, GlobalSettings.ReservedPaths)
|
||||
|| !object.ReferenceEquals(_reservedUrlsCache, GlobalSettings.ReservedUrls))
|
||||
{
|
||||
if (_reservedUrlsCache == null)
|
||||
{
|
||||
// store references to strings to determine changes
|
||||
_reservedPathsCache = GlobalSettings.ReservedPaths;
|
||||
_reservedUrlsCache = GlobalSettings.ReservedUrls;
|
||||
|
||||
string _root = SystemDirectories.Root.Trim().ToLower();
|
||||
|
||||
// add URLs and paths to a new list
|
||||
StartsWithContainer _newReservedList = new StartsWithContainer();
|
||||
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
lock (Locker)
|
||||
{
|
||||
//resolves the url to support tilde chars
|
||||
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower();
|
||||
if (reservedUrlTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedUrlTrimmed);
|
||||
if (_reservedUrlsCache == null)
|
||||
{
|
||||
// store references to strings to determine changes
|
||||
_reservedPathsCache = GlobalSettings.ReservedPaths;
|
||||
_reservedUrlsCache = GlobalSettings.ReservedUrls;
|
||||
|
||||
string _root = SystemDirectories.Root.Trim().ToLower();
|
||||
|
||||
// add URLs and paths to a new list
|
||||
StartsWithContainer _newReservedList = new StartsWithContainer();
|
||||
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
//resolves the url to support tilde chars
|
||||
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower();
|
||||
if (reservedUrlTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedUrlTrimmed);
|
||||
}
|
||||
|
||||
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
bool trimEnd = !reservedPath.EndsWith("/");
|
||||
//resolves the url to support tilde chars
|
||||
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower();
|
||||
|
||||
if (reservedPathTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
|
||||
}
|
||||
|
||||
// use the new list from now on
|
||||
_reservedList = _newReservedList;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
bool trimEnd = !reservedPath.EndsWith("/");
|
||||
//resolves the url to support tilde chars
|
||||
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower();
|
||||
|
||||
if (reservedPathTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
|
||||
}
|
||||
|
||||
// use the new list from now on
|
||||
_reservedList = _newReservedList;
|
||||
}
|
||||
|
||||
//The url should be cleaned up before checking:
|
||||
|
||||
@@ -25,6 +25,43 @@ namespace Umbraco.Core.Configuration
|
||||
/// </summary>
|
||||
internal class UmbracoSettings
|
||||
{
|
||||
private static bool GetKeyValue(string key, bool defaultValue)
|
||||
{
|
||||
bool value;
|
||||
string stringValue = GetKey(key);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(stringValue))
|
||||
return defaultValue;
|
||||
if (bool.TryParse(stringValue, out value))
|
||||
return value;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static int GetKeyValue(string key, int defaultValue)
|
||||
{
|
||||
int value;
|
||||
string stringValue = GetKey(key);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(stringValue))
|
||||
return defaultValue;
|
||||
if (int.TryParse(stringValue, out value))
|
||||
return value;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
|
||||
/// </summary>
|
||||
internal static void ResetSetters()
|
||||
{
|
||||
_addTrailingSlash = null;
|
||||
_forceSafeAliases = null;
|
||||
_useLegacySchema = null;
|
||||
_useDomainPrefixes = null;
|
||||
_umbracoLibraryCacheDuration = null;
|
||||
_trySkipIisCustomErrors = null;
|
||||
}
|
||||
|
||||
internal const string TempFriendlyXmlChildContainerNodename = ""; // "children";
|
||||
|
||||
/// <summary>
|
||||
@@ -113,11 +150,32 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
EnsureSettingsDocument();
|
||||
|
||||
string attrName = null;
|
||||
var pos = key.IndexOf('@');
|
||||
if (pos > 0)
|
||||
{
|
||||
attrName = key.Substring(pos + 1);
|
||||
key = key.Substring(0, pos - 1);
|
||||
}
|
||||
|
||||
var node = UmbracoSettingsXmlDoc.DocumentElement.SelectSingleNode(key);
|
||||
if (node == null || node.FirstChild == null || node.FirstChild.Value == null)
|
||||
return string.Empty;
|
||||
return node.FirstChild.Value;
|
||||
}
|
||||
if (node == null)
|
||||
return string.Empty;
|
||||
|
||||
if (pos < 0)
|
||||
{
|
||||
if (node.FirstChild == null || node.FirstChild.Value == null)
|
||||
return string.Empty;
|
||||
return node.FirstChild.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var attr = node.Attributes[attrName];
|
||||
if (attr == null)
|
||||
return string.Empty;
|
||||
return attr.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the media library will create new directories in the /media directory.
|
||||
@@ -190,6 +248,7 @@ namespace Umbraco.Core.Configuration
|
||||
return value != null ? value.Attributes["assembly"].Value : "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of an external logger that can be used to store log items in 3rd party systems
|
||||
/// </summary>
|
||||
@@ -338,24 +397,13 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_useDomainPrefixes.HasValue)
|
||||
return _useDomainPrefixes.Value;
|
||||
bool result;
|
||||
if (bool.TryParse(GetKey("/settings/requestHandler/useDomainPrefixes"), out result))
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// default: false
|
||||
return _useDomainPrefixes ?? GetKeyValue("/settings/requestHandler/useDomainPrefixes", false);
|
||||
}
|
||||
// for unit tests only
|
||||
internal set
|
||||
{
|
||||
_useDomainPrefixes = value;
|
||||
// for unit tests only
|
||||
_useDomainPrefixes = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,31 +417,14 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (GlobalSettings.UseDirectoryUrls)
|
||||
{
|
||||
if (_addTrailingSlash.HasValue)
|
||||
return _addTrailingSlash.Value;
|
||||
bool result;
|
||||
if (bool.TryParse(GetKey("/settings/requestHandler/addTrailingSlash"), out result))
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// default: false
|
||||
return GlobalSettings.UseDirectoryUrls
|
||||
&& (_addTrailingSlash ?? GetKeyValue("/settings/requestHandler/addTrailingSlash", false));
|
||||
}
|
||||
// for unit tests only
|
||||
internal set
|
||||
{
|
||||
_addTrailingSlash = value;
|
||||
// for unit tests only
|
||||
_addTrailingSlash = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,6 +632,8 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
private static bool? _forceSafeAliases;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to force safe aliases (no spaces, no special characters) at businesslogic level on contenttypes and propertytypes
|
||||
/// </summary>
|
||||
@@ -608,24 +641,34 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
string forceSafeAlias = GetKey("/settings/content/ForceSafeAliases");
|
||||
if (String.IsNullOrEmpty(forceSafeAlias))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
return bool.Parse(forceSafeAlias);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// default: true
|
||||
return _forceSafeAliases ?? GetKeyValue("/settings/content/ForceSafeAliases", true);
|
||||
}
|
||||
internal set
|
||||
{
|
||||
// used for unit testing
|
||||
_forceSafeAliases = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool? _trySkipIisCustomErrors;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating where to try to skip IIS custom errors.
|
||||
/// </summary>
|
||||
public static bool TrySkipIisCustomErrors
|
||||
{
|
||||
get
|
||||
{
|
||||
// default: false
|
||||
return _trySkipIisCustomErrors ?? GetKeyValue("/settings/web.routing/@trySkipIisCustomErrors", false);
|
||||
}
|
||||
internal set
|
||||
{
|
||||
// used for unit testing
|
||||
_trySkipIisCustomErrors = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the allowed image file types.
|
||||
@@ -645,6 +688,8 @@ namespace Umbraco.Core.Configuration
|
||||
get { return GetKey("/settings/content/scripteditor/scriptFileTypes"); }
|
||||
}
|
||||
|
||||
private static int? _umbracoLibraryCacheDuration;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration in seconds to cache queries to umbraco library member and media methods
|
||||
/// Default is 1800 seconds (30 minutes)
|
||||
@@ -653,22 +698,14 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
string libraryCacheDuration = GetKey("/settings/content/UmbracoLibraryCacheDuration");
|
||||
if (String.IsNullOrEmpty(libraryCacheDuration))
|
||||
return 1800;
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
return int.Parse(libraryCacheDuration);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 1800;
|
||||
}
|
||||
}
|
||||
|
||||
// default: 1800
|
||||
return _umbracoLibraryCacheDuration ?? GetKeyValue("/settings/content/UmbracoLibraryCacheDuration", 1800);
|
||||
}
|
||||
internal set
|
||||
{
|
||||
// for unit tests only
|
||||
_umbracoLibraryCacheDuration = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1024,27 +1061,12 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_useLegacySchema.HasValue)
|
||||
return _useLegacySchema.Value;
|
||||
|
||||
string value = GetKey("/settings/content/UseLegacyXmlSchema");
|
||||
bool result;
|
||||
if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result))
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//default. TODO: When we change this to a real config section we won't have to worry about parse errors
|
||||
// and should handle defaults with unit tests properly.
|
||||
return false;
|
||||
}
|
||||
// default: true
|
||||
return _useLegacySchema ?? GetKeyValue("/settings/content/UseLegacyXmlSchema", false);
|
||||
}
|
||||
internal set
|
||||
{
|
||||
//used for unit testing
|
||||
// used for unit testing
|
||||
_useLegacySchema = value;
|
||||
}
|
||||
}
|
||||
@@ -1193,6 +1215,40 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
private static MacroErrorBehaviour? _macroErrorBehaviour;
|
||||
|
||||
/// <summary>
|
||||
/// This configuration setting defines how to handle macro errors:
|
||||
/// - Inline - Show error within macro as text (default and current Umbraco 'normal' behavior)
|
||||
/// - Silent - Suppress error and hide macro
|
||||
/// - Throw - Throw an exception and invoke the global error handler (if one is defined, if not you'll get a YSOD)
|
||||
/// </summary>
|
||||
/// <value>MacroErrorBehaviour enum defining how to handle macro errors.</value>
|
||||
public static MacroErrorBehaviour MacroErrorBehaviour
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_macroErrorBehaviour == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var behaviour = MacroErrorBehaviour.Inline;
|
||||
var value = GetKey("/settings/content/MacroErrors");
|
||||
if (value != null)
|
||||
{
|
||||
Enum<MacroErrorBehaviour>.TryParse(value, true, out behaviour);
|
||||
}
|
||||
_macroErrorBehaviour = behaviour;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<UmbracoSettings>("Could not load /settings/content/MacroErrors from umbracosettings.config", ex);
|
||||
_macroErrorBehaviour = MacroErrorBehaviour.Inline;
|
||||
}
|
||||
}
|
||||
return _macroErrorBehaviour.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration regarding webservices
|
||||
|
||||
@@ -32,8 +32,7 @@ namespace Umbraco.Core
|
||||
LogHelper.Info<CoreBootManager>("Umbraco application starting");
|
||||
_timer = DisposableTimer.Start(x => LogHelper.Info<CoreBootManager>("Umbraco application startup complete" + " (took " + x + "ms)"));
|
||||
|
||||
//create the ApplicationContext
|
||||
ApplicationContext = ApplicationContext.Current = new ApplicationContext();
|
||||
CreateApplicationContext();
|
||||
|
||||
InitializeResolvers();
|
||||
|
||||
@@ -42,6 +41,15 @@ namespace Umbraco.Core
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and assigns the application context singleton
|
||||
/// </summary>
|
||||
protected virtual void CreateApplicationContext()
|
||||
{
|
||||
//create the ApplicationContext
|
||||
ApplicationContext = ApplicationContext.Current = new ApplicationContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires after initialization and calls the callback to allow for customizations to occur
|
||||
/// </summary>
|
||||
@@ -72,8 +80,7 @@ namespace Umbraco.Core
|
||||
if (_isComplete)
|
||||
throw new InvalidOperationException("The boot manager has already been completed");
|
||||
|
||||
//freeze resolution to not allow Resolvers to be modified
|
||||
Resolution.Freeze();
|
||||
FreezeResolution();
|
||||
|
||||
//stop the timer and log the output
|
||||
_timer.Dispose();
|
||||
@@ -88,25 +95,33 @@ namespace Umbraco.Core
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freeze resolution to not allow Resolvers to be modified
|
||||
/// </summary>
|
||||
protected virtual void FreezeResolution()
|
||||
{
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the resolvers
|
||||
/// </summary>
|
||||
protected virtual void InitializeResolvers()
|
||||
{
|
||||
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
|
||||
PluginManager.Current.ResolveCacheRefreshers());
|
||||
() => PluginManager.Current.ResolveCacheRefreshers());
|
||||
|
||||
DataTypesResolver.Current = new DataTypesResolver(
|
||||
PluginManager.Current.ResolveDataTypes());
|
||||
() => PluginManager.Current.ResolveDataTypes());
|
||||
|
||||
MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver(
|
||||
PluginManager.Current.ResolveMacroRenderings());
|
||||
() => PluginManager.Current.ResolveMacroRenderings());
|
||||
|
||||
PackageActionsResolver.Current = new PackageActionsResolver(
|
||||
PluginManager.Current.ResolvePackageActions());
|
||||
() => PluginManager.Current.ResolvePackageActions());
|
||||
|
||||
ActionsResolver.Current = new ActionsResolver(
|
||||
PluginManager.Current.ResolveActions());
|
||||
() => PluginManager.Current.ResolveActions());
|
||||
|
||||
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
|
||||
PluginManager.Current.ResolvePropertyEditorValueConverters());
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
var str = (string)value;
|
||||
if (str == "1") return true;
|
||||
if (str == "0") return false;
|
||||
if (str == "0" || str == "") return false;
|
||||
}
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="dataTypes"></param>
|
||||
internal DataTypesResolver(IEnumerable<Type> dataTypes)
|
||||
internal DataTypesResolver(Func<IEnumerable<Type>> dataTypes)
|
||||
: base(dataTypes)
|
||||
{
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Dictionary
|
||||
/// <summary>
|
||||
/// Resolves the current CultureDictionaryFactory
|
||||
/// </summary>
|
||||
internal class CultureDictionaryFactoryResolver : SingleObjectResolverBase<CultureDictionaryFactoryResolver, ICultureDictionaryFactory>
|
||||
internal sealed class CultureDictionaryFactoryResolver : SingleObjectResolverBase<CultureDictionaryFactoryResolver, ICultureDictionaryFactory>
|
||||
{
|
||||
internal CultureDictionaryFactoryResolver(ICultureDictionaryFactory factory)
|
||||
: base(factory)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -158,7 +159,7 @@ namespace Umbraco.Core
|
||||
var builder = new StringBuilder();
|
||||
foreach (var i in d)
|
||||
{
|
||||
builder.Append(String.Format("{0}={1}&", i.Key, i.Value));
|
||||
builder.Append(String.Format("{0}={1}&", HttpUtility.UrlEncode(i.Key), i.Value == null ? string.Empty : HttpUtility.UrlEncode(i.Value.ToString())));
|
||||
}
|
||||
return builder.ToString().TrimEnd('&');
|
||||
}
|
||||
|
||||
@@ -4,99 +4,135 @@ using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// Console.WriteLine("Testing Stopwatchdisposable, should be 567:");
|
||||
// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
|
||||
// {
|
||||
// Thread.Sleep(567);
|
||||
// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class DisposableTimer : DisposableObject
|
||||
{
|
||||
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
|
||||
private readonly Action<long> _callback;
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// Console.WriteLine("Testing Stopwatchdisposable, should be 567:");
|
||||
// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
|
||||
// {
|
||||
// Thread.Sleep(567);
|
||||
// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class DisposableTimer : DisposableObject
|
||||
{
|
||||
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
|
||||
private readonly Action<long> _callback;
|
||||
|
||||
protected DisposableTimer(Action<long> callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
protected DisposableTimer(Action<long> callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
public Stopwatch Stopwatch
|
||||
{
|
||||
get { return _stopwatch; }
|
||||
}
|
||||
public Stopwatch Stopwatch
|
||||
{
|
||||
get { return _stopwatch; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes the specified callback upon disposal.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback.</param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer Start(Action<long> callback)
|
||||
{
|
||||
return new DisposableTimer(callback);
|
||||
}
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes the specified callback upon disposal.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback.</param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer Start(Action<long> callback)
|
||||
{
|
||||
return new DisposableTimer(callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
public static DisposableTimer TraceDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Info(loggerType, () => startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)"));
|
||||
}
|
||||
public static DisposableTimer TraceDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, () => startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)"));
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Info(loggerType, () => startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, () => startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
public static DisposableTimer DebugDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, startMessage);
|
||||
return new DisposableTimer(x => LogHelper.Debug(loggerType, () => completeMessage() + " (took " + x + "ms)"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper class to try invoke members, find properties, etc...
|
||||
/// </summary>
|
||||
internal class DynamicInstanceHelper
|
||||
{
|
||||
|
||||
internal class TryInvokeMemberResult
|
||||
{
|
||||
public object ObjectResult { get; private set; }
|
||||
public TryInvokeMemberSuccessReason Reason { get; private set; }
|
||||
|
||||
public TryInvokeMemberResult(object result, TryInvokeMemberSuccessReason reason)
|
||||
{
|
||||
ObjectResult = result;
|
||||
Reason = reason;
|
||||
}
|
||||
}
|
||||
|
||||
internal enum TryInvokeMemberSuccessReason
|
||||
{
|
||||
FoundProperty,
|
||||
FoundMethod,
|
||||
FoundExtensionMethod
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to invoke a member based on the dynamic instance
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="thisObject">The object instance to invoke the extension method for</param>
|
||||
/// <param name="binder"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// First tries to find a property with the binder name, if that fails it will try to find a static or instance method
|
||||
/// on the object that matches the binder name
|
||||
/// </remarks>
|
||||
public static Attempt<TryInvokeMemberResult> TryInvokeMember<T>(T thisObject, InvokeMemberBinder binder, object[] args)
|
||||
{
|
||||
return TryInvokeMember<T>(thisObject, binder, args, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to invoke a member based on the dynamic instance
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="thisObject">The object instance to invoke the extension method for</param>
|
||||
/// <param name="binder"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="findExtensionMethodsOnTypes">The types to scan for extension methods </param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// First tries to find a property with the binder name, if that fails it will try to find a static or instance method
|
||||
/// on the object that matches the binder name, if that fails it will then attempt to invoke an extension method
|
||||
/// based on the binder name and the extension method types to scan.
|
||||
/// </remarks>
|
||||
public static Attempt<TryInvokeMemberResult> TryInvokeMember<T>(T thisObject,
|
||||
InvokeMemberBinder binder,
|
||||
object[] args,
|
||||
IEnumerable<Type> findExtensionMethodsOnTypes)
|
||||
{
|
||||
//TODO: We MUST cache the result here, it is very expensive to keep finding extension methods!
|
||||
object result;
|
||||
try
|
||||
{
|
||||
//Property?
|
||||
result = typeof(T).InvokeMember(binder.Name,
|
||||
System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.Public |
|
||||
System.Reflection.BindingFlags.GetProperty,
|
||||
null,
|
||||
thisObject,
|
||||
args);
|
||||
return new Attempt<TryInvokeMemberResult>(true, new TryInvokeMemberResult(result, TryInvokeMemberSuccessReason.FoundProperty));
|
||||
}
|
||||
catch (MissingMethodException)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Static or Instance Method?
|
||||
result = typeof(T).InvokeMember(binder.Name,
|
||||
System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.Public |
|
||||
System.Reflection.BindingFlags.Static |
|
||||
System.Reflection.BindingFlags.InvokeMethod,
|
||||
null,
|
||||
thisObject,
|
||||
args);
|
||||
return new Attempt<TryInvokeMemberResult>(true, new TryInvokeMemberResult(result, TryInvokeMemberSuccessReason.FoundMethod));
|
||||
}
|
||||
catch (MissingMethodException)
|
||||
{
|
||||
if (findExtensionMethodsOnTypes != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = FindAndExecuteExtensionMethod(thisObject, args, binder.Name, findExtensionMethodsOnTypes);
|
||||
return new Attempt<TryInvokeMemberResult>(true, new TryInvokeMemberResult(result, TryInvokeMemberSuccessReason.FoundExtensionMethod));
|
||||
}
|
||||
catch (TargetInvocationException ext)
|
||||
{
|
||||
//don't log here, we return this exception because the caller may need to do something specific when
|
||||
//this exception occurs.
|
||||
return new Attempt<TryInvokeMemberResult>(ext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var sb = new StringBuilder("An error occurred finding an executing an extension method for type ");
|
||||
sb.Append(typeof (T));
|
||||
sb.Append("Types searched for extension methods were ");
|
||||
foreach(var t in findExtensionMethodsOnTypes)
|
||||
{
|
||||
sb.Append(t + ",");
|
||||
}
|
||||
LogHelper.Error<DynamicInstanceHelper>(sb.ToString(), ex);
|
||||
return new Attempt<TryInvokeMemberResult>(ex);
|
||||
}
|
||||
}
|
||||
return Attempt<TryInvokeMemberResult>.False;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<DynamicInstanceHelper>("An unhandled exception occurred in method TryInvokeMember", ex);
|
||||
return new Attempt<TryInvokeMemberResult>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to find an extension method that matches the name and arguments based on scanning the Type's passed in
|
||||
/// to the findMethodsOnTypes parameter
|
||||
/// </summary>
|
||||
/// <param name="thisObject">The instance object to execute the extension method for</param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="findMethodsOnTypes"></param>
|
||||
/// <returns></returns>
|
||||
internal static object FindAndExecuteExtensionMethod<T>(T thisObject,
|
||||
object[] args,
|
||||
string name,
|
||||
IEnumerable<Type> findMethodsOnTypes)
|
||||
{
|
||||
object result = null;
|
||||
|
||||
//find known extension methods that match the first type in the list
|
||||
MethodInfo toExecute = null;
|
||||
foreach (var t in findMethodsOnTypes)
|
||||
{
|
||||
toExecute = ExtensionMethodFinder.FindExtensionMethod(t, args, name, false);
|
||||
if (toExecute != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (toExecute != null)
|
||||
{
|
||||
var genericArgs = (new[] { (object)thisObject }).Concat(args);
|
||||
result = toExecute.Invoke(null, genericArgs.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MissingMethodException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Dynamic;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using System.Collections;
|
||||
@@ -10,7 +11,7 @@ using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
public class DynamicXml : DynamicObject, IEnumerable
|
||||
public class DynamicXml : DynamicObject, IEnumerable<DynamicXml>, IEnumerable<XElement>
|
||||
{
|
||||
public XElement BaseElement { get; set; }
|
||||
|
||||
@@ -70,7 +71,53 @@ namespace Umbraco.Core.Dynamics
|
||||
HandleIEnumerableXElement(elements, out result);
|
||||
return true; //anyway
|
||||
}
|
||||
return base.TryInvokeMember(binder, args, out result);
|
||||
|
||||
//ok, now lets try to match by member, property, extensino method
|
||||
var attempt = DynamicInstanceHelper.TryInvokeMember(this, binder, args, new[]
|
||||
{
|
||||
typeof (IEnumerable<DynamicXml>),
|
||||
typeof (IEnumerable<XElement>),
|
||||
typeof (DynamicXml)
|
||||
});
|
||||
|
||||
if (attempt.Success)
|
||||
{
|
||||
result = attempt.Result.ObjectResult;
|
||||
|
||||
//need to check the return type and possibly cast if result is from an extension method found
|
||||
if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod)
|
||||
{
|
||||
//if the result is already a DynamicXml instance, then we do not need to cast
|
||||
if (attempt.Result.ObjectResult != null && !(attempt.Result.ObjectResult is DynamicXml))
|
||||
{
|
||||
if (attempt.Result.ObjectResult is XElement)
|
||||
{
|
||||
result = new DynamicXml((XElement)attempt.Result.ObjectResult);
|
||||
}
|
||||
else if (attempt.Result.ObjectResult is IEnumerable<XElement>)
|
||||
{
|
||||
result = ((IEnumerable<XElement>)attempt.Result.ObjectResult).Select(x => new DynamicXml(x));
|
||||
}
|
||||
else if (attempt.Result.ObjectResult is IEnumerable<DynamicXml>)
|
||||
{
|
||||
result = ((IEnumerable<DynamicXml>)attempt.Result.ObjectResult).Select(x => new DynamicXml(x.BaseElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//this is the result of an extension method execution gone wrong so we return dynamic null
|
||||
if (attempt.Result.Reason == DynamicInstanceHelper.TryInvokeMemberSuccessReason.FoundExtensionMethod
|
||||
&& attempt.Error != null && attempt.Error is TargetInvocationException)
|
||||
{
|
||||
result = new DynamicNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
|
||||
}
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
@@ -181,18 +228,39 @@ namespace Umbraco.Core.Dynamics
|
||||
return new DynamicXml(this.BaseElement.XPathSelectElements(expression).FirstOrDefault());
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
IEnumerator<XElement> IEnumerable<XElement>.GetEnumerator()
|
||||
{
|
||||
return this.BaseElement.Elements().GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<DynamicXml> GetEnumerator()
|
||||
{
|
||||
return this.BaseElement.Elements().Select(e => new DynamicXml(e)).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public int Count()
|
||||
{
|
||||
return this.BaseElement.Elements().Count();
|
||||
return ((IEnumerable<XElement>)this).Count();
|
||||
}
|
||||
|
||||
public bool Any()
|
||||
{
|
||||
return this.BaseElement.Elements().Any();
|
||||
return ((IEnumerable<XElement>)this).Any();
|
||||
}
|
||||
|
||||
public IEnumerable<DynamicXml> Take(int count)
|
||||
{
|
||||
return ((IEnumerable<DynamicXml>)this).Take(count);
|
||||
}
|
||||
|
||||
public IEnumerable<DynamicXml> Skip(int count)
|
||||
{
|
||||
return ((IEnumerable<DynamicXml>)this).Skip(count);
|
||||
}
|
||||
|
||||
public bool IsNull()
|
||||
@@ -435,86 +503,88 @@ namespace Umbraco.Core.Dynamics
|
||||
public HtmlString IsDescendant(DynamicXml other, string valueIfTrue)
|
||||
{
|
||||
var ancestors = this.Ancestors();
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
}
|
||||
public HtmlString IsDescendant(DynamicXml other, string valueIfTrue, string valueIfFalse)
|
||||
{
|
||||
var ancestors = this.Ancestors();
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
}
|
||||
public bool IsDescendantOrSelf(DynamicXml other)
|
||||
{
|
||||
var ancestors = this.AncestorsOrSelf();
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null);
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null);
|
||||
}
|
||||
public HtmlString IsDescendantOrSelf(DynamicXml other, string valueIfTrue)
|
||||
{
|
||||
var ancestors = this.AncestorsOrSelf();
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
}
|
||||
public HtmlString IsDescendantOrSelf(DynamicXml other, string valueIfTrue, string valueIfFalse)
|
||||
{
|
||||
var ancestors = this.AncestorsOrSelf();
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
return IsHelper(n => ancestors.FirstOrDefault(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
}
|
||||
public bool IsAncestor(DynamicXml other)
|
||||
{
|
||||
var descendants = this.Descendants();
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
|
||||
}
|
||||
public HtmlString IsAncestor(DynamicXml other, string valueIfTrue)
|
||||
{
|
||||
var descendants = this.Descendants();
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
}
|
||||
public HtmlString IsAncestor(DynamicXml other, string valueIfTrue, string valueIfFalse)
|
||||
{
|
||||
var descendants = this.Descendants();
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
}
|
||||
public bool IsAncestorOrSelf(DynamicXml other)
|
||||
{
|
||||
var descendants = this.DescendantsOrSelf();
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null);
|
||||
}
|
||||
public HtmlString IsAncestorOrSelf(DynamicXml other, string valueIfTrue)
|
||||
{
|
||||
var descendants = this.DescendantsOrSelf();
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
|
||||
}
|
||||
public HtmlString IsAncestorOrSelf(DynamicXml other, string valueIfTrue, string valueIfFalse)
|
||||
{
|
||||
var descendants = this.DescendantsOrSelf();
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
return IsHelper(n => descendants.FirstOrDefault(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
|
||||
}
|
||||
public IEnumerable<DynamicXml> Descendants()
|
||||
{
|
||||
return Descendants(n => true);
|
||||
}
|
||||
public IEnumerable<DynamicXml> Descendants(Func<XElement, bool> func)
|
||||
public IEnumerable<DynamicXml> Descendants(Func<XElement, bool> func)
|
||||
{
|
||||
var flattenedNodes = this.BaseElement.Elements().Map(func, (XElement n) => { return n.Elements(); });
|
||||
//var flattenedNodes = this.BaseElement.Elements().Map(func, n => n.Elements());
|
||||
var flattenedNodes = this.BaseElement.Elements().SelectMany(n => n.Elements()).Where(func);
|
||||
return flattenedNodes.ToList().ConvertAll(n => new DynamicXml(n));
|
||||
}
|
||||
public IEnumerable<DynamicXml> DescendantsOrSelf()
|
||||
public IEnumerable<DynamicXml> DescendantsOrSelf()
|
||||
{
|
||||
return DescendantsOrSelf(n => true);
|
||||
}
|
||||
public IEnumerable<DynamicXml> DescendantsOrSelf(Func<XElement, bool> func)
|
||||
public IEnumerable<DynamicXml> DescendantsOrSelf(Func<XElement, bool> func)
|
||||
{
|
||||
var flattenedNodes = this.BaseElement.Elements().Map(func, (XElement n) => { return n.Elements(); });
|
||||
//var flattenedNodes = this.BaseElement.Elements().Map(func, n => n.Elements());
|
||||
var flattenedNodes = this.BaseElement.Elements().SelectMany(n => n.Elements()).Where(func);
|
||||
var list = new List<DynamicXml>();
|
||||
list.Add(this);
|
||||
list.AddRange(flattenedNodes.ToList().ConvertAll(n => new DynamicXml(n)));
|
||||
return list;
|
||||
}
|
||||
public IEnumerable<DynamicXml> Ancestors()
|
||||
public IEnumerable<DynamicXml> Ancestors()
|
||||
{
|
||||
return Ancestors(item => true);
|
||||
}
|
||||
public IEnumerable<DynamicXml> Ancestors(Func<XElement, bool> func)
|
||||
public IEnumerable<DynamicXml> Ancestors(Func<XElement, bool> func)
|
||||
{
|
||||
List<XElement> ancestorList = new List<XElement>();
|
||||
var ancestorList = new List<XElement>();
|
||||
var node = this.BaseElement;
|
||||
while (node != null)
|
||||
{
|
||||
@@ -543,11 +613,11 @@ namespace Umbraco.Core.Dynamics
|
||||
ancestorList.Reverse();
|
||||
return ancestorList.ConvertAll(item => new DynamicXml(item));
|
||||
}
|
||||
public IEnumerable<DynamicXml> AncestorsOrSelf()
|
||||
public IEnumerable<DynamicXml> AncestorsOrSelf()
|
||||
{
|
||||
return AncestorsOrSelf(item => true);
|
||||
}
|
||||
public IEnumerable<DynamicXml> AncestorsOrSelf(Func<XElement, bool> func)
|
||||
public IEnumerable<DynamicXml> AncestorsOrSelf(Func<XElement, bool> func)
|
||||
{
|
||||
List<XElement> ancestorList = new List<XElement>();
|
||||
var node = this.BaseElement;
|
||||
@@ -661,5 +731,7 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Dynamics
|
||||
);
|
||||
|
||||
//add the extension methods defined in IEnumerable
|
||||
candidates = candidates.Concat(typeof(IEnumerable).GetMethods(BindingFlags.Static | BindingFlags.Public));
|
||||
candidates = candidates.Concat(typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public));
|
||||
|
||||
//filter by name
|
||||
var methodsByName = candidates.Where(m => m.Name == name);
|
||||
|
||||
@@ -5,36 +5,35 @@ using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.Dynamics
|
||||
{
|
||||
[Obsolete("This class should not be used, it is just referenced by already obsoleted code and will be removed in the future")]
|
||||
internal static class ExtensionMethods
|
||||
{
|
||||
public static IEnumerable<TSource> Map<TSource>(
|
||||
this IEnumerable<TSource> source,
|
||||
Func<TSource, bool> selectorFunction,
|
||||
Func<TSource, IEnumerable<TSource>> getChildrenFunction)
|
||||
{
|
||||
if (!source.Any())
|
||||
{
|
||||
return source;
|
||||
}
|
||||
// Add what we have to the stack
|
||||
var flattenedList = source.Where(selectorFunction);
|
||||
// Go through the input enumerable looking for children,
|
||||
// and add those if we have them
|
||||
foreach (TSource element in source)
|
||||
{
|
||||
var secondInner = getChildrenFunction(element);
|
||||
if (secondInner.Any())
|
||||
{
|
||||
secondInner = secondInner.Map(selectorFunction, getChildrenFunction);
|
||||
}
|
||||
flattenedList = flattenedList.Concat(secondInner);
|
||||
}
|
||||
return flattenedList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//public static IEnumerable<TSource> Map<TSource>(
|
||||
// this IEnumerable<TSource> source,
|
||||
// Func<TSource, bool> selectorFunction,
|
||||
// Func<TSource, IEnumerable<TSource>> getChildrenFunction)
|
||||
//{
|
||||
// if (!source.Any())
|
||||
// {
|
||||
// return source;
|
||||
// }
|
||||
// // Add what we have to the stack
|
||||
// var flattenedList = source.Where(selectorFunction);
|
||||
// // Go through the input enumerable looking for children,
|
||||
// // and add those if we have them
|
||||
// foreach (TSource element in source)
|
||||
// {
|
||||
// var secondInner = getChildrenFunction(element);
|
||||
// if (secondInner.Any())
|
||||
// {
|
||||
// secondInner = secondInner.Map(selectorFunction, getChildrenFunction);
|
||||
// }
|
||||
// flattenedList = flattenedList.Concat(secondInner);
|
||||
// }
|
||||
// return flattenedList;
|
||||
//}
|
||||
|
||||
[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");
|
||||
@@ -44,6 +43,7 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
return false;
|
||||
}
|
||||
[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");
|
||||
@@ -53,6 +53,7 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
return false;
|
||||
}
|
||||
[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");
|
||||
@@ -62,6 +63,7 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
return false;
|
||||
}
|
||||
[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");
|
||||
@@ -71,12 +73,13 @@ namespace Umbraco.Core.Dynamics
|
||||
}
|
||||
return false;
|
||||
}
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool ContainsInsensitive(this string haystack, string needle)
|
||||
{
|
||||
if (haystack == null) throw new ArgumentNullException("haystack");
|
||||
return haystack.IndexOf(needle, StringComparison.CurrentCultureIgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
[Obsolete("This method should not be used and will be removed in the future")]
|
||||
public static bool HasValue(this string s)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(s);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
// Provides information on the macro that caused an error
|
||||
public class MacroErrorEventArgs : System.EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the faulting macro.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Alias of the faulting macro.
|
||||
/// </summary>
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Filename, file path, fully qualified class name, or other key used by the macro engine to do it's processing of the faulting macro.
|
||||
/// </summary>
|
||||
public string ItemKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exception raised.
|
||||
/// </summary>
|
||||
public Exception Exception { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the desired behaviour when a matching macro causes an error. See
|
||||
/// <see cref="MacroErrorBehaviour"/> for definitions. By setting this in your event
|
||||
/// you can override the default behaviour defined in UmbracoSettings.config.
|
||||
/// </summary>
|
||||
/// <value>Macro error behaviour enum.</value>
|
||||
public MacroErrorBehaviour Behaviour { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to create a hash code from multiple objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
|
||||
/// which we've not included here as we just need a quick easy class for this in order to create a unique
|
||||
/// hash of directories/files to see if they have changed.
|
||||
/// </remarks>
|
||||
internal class HashCodeCombiner
|
||||
{
|
||||
private long _combinedHash = 5381L;
|
||||
|
||||
internal void AddInt(int i)
|
||||
{
|
||||
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
|
||||
}
|
||||
|
||||
internal void AddObject(object o)
|
||||
{
|
||||
AddInt(o.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddDateTime(DateTime d)
|
||||
{
|
||||
AddInt(d.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddCaseInsensitiveString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
|
||||
}
|
||||
|
||||
internal void AddFileSystemItem(FileSystemInfo f)
|
||||
{
|
||||
//if it doesn't exist, don't proceed.
|
||||
if (!f.Exists)
|
||||
return;
|
||||
|
||||
AddCaseInsensitiveString(f.FullName);
|
||||
AddDateTime(f.CreationTimeUtc);
|
||||
AddDateTime(f.LastWriteTimeUtc);
|
||||
|
||||
//check if it is a file or folder
|
||||
var fileInfo = f as FileInfo;
|
||||
if (fileInfo != null)
|
||||
{
|
||||
AddInt(fileInfo.Length.GetHashCode());
|
||||
}
|
||||
|
||||
var dirInfo = f as DirectoryInfo;
|
||||
if (dirInfo != null)
|
||||
{
|
||||
foreach (var d in dirInfo.GetFiles())
|
||||
{
|
||||
AddFile(d);
|
||||
}
|
||||
foreach (var s in dirInfo.GetDirectories())
|
||||
{
|
||||
AddFolder(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddFile(FileInfo f)
|
||||
{
|
||||
AddFileSystemItem(f);
|
||||
}
|
||||
|
||||
internal void AddFolder(DirectoryInfo d)
|
||||
{
|
||||
AddFileSystemItem(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hex code of the combined hash code
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal string GetCombinedHashCode()
|
||||
{
|
||||
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,7 @@ namespace Umbraco.Core.IO
|
||||
///
|
||||
/// This abstract class just wraps the 'real' IFileSystem object passed in to its constructor.
|
||||
/// </remarks>
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
internal abstract class FileSystemWrapper : IFileSystem
|
||||
public abstract class FileSystemWrapper : IFileSystem
|
||||
{
|
||||
private readonly IFileSystem _wrapped;
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@ using System.IO;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
internal interface IFileSystem
|
||||
{
|
||||
public interface IFileSystem
|
||||
{
|
||||
IEnumerable<string> GetDirectories(string path);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.IO;
|
||||
using System.Configuration;
|
||||
using System.Web;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -220,7 +221,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
foreach (var character in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
filePath = filePath.Replace(character, '_');
|
||||
filePath = filePath.Replace(character, '-');
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -228,6 +229,20 @@ namespace Umbraco.Core.IO
|
||||
filePath = String.Empty;
|
||||
}
|
||||
|
||||
//Break up the file in name and extension before applying the UrlReplaceCharacters
|
||||
var fileNamePart = filePath.Substring(0, filePath.LastIndexOf('.'));
|
||||
var ext = filePath.Substring(filePath.LastIndexOf('.'));
|
||||
|
||||
//Because the file usually is downloadable as well we check characters against 'UmbracoSettings.UrlReplaceCharacters'
|
||||
XmlNode replaceChars = UmbracoSettings.UrlReplaceCharacters;
|
||||
foreach (XmlNode n in replaceChars.SelectNodes("char"))
|
||||
{
|
||||
if (n.Attributes.GetNamedItem("org") != null && n.Attributes.GetNamedItem("org").Value != "")
|
||||
fileNamePart = fileNamePart.Replace(n.Attributes.GetNamedItem("org").Value, XmlHelper.GetNodeValue(n));
|
||||
}
|
||||
|
||||
filePath = string.Concat(fileNamePart, ext);
|
||||
|
||||
// Adapted from: http://stackoverflow.com/a/4827510/5018
|
||||
// Combined both Reserved Characters and Character Data
|
||||
// from http://en.wikipedia.org/wiki/Percent-encoding
|
||||
@@ -240,10 +255,14 @@ namespace Umbraco.Core.IO
|
||||
if (reservedCharacters.IndexOf(character) == -1)
|
||||
stringBuilder.Append(character);
|
||||
else
|
||||
stringBuilder.Append("_");
|
||||
stringBuilder.Append("-");
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
// Remove repeating dashes
|
||||
// From: http://stackoverflow.com/questions/5111967/regex-to-remove-a-specific-repeated-character
|
||||
var reducedString = Regex.Replace(stringBuilder.ToString(), "-+", "-");
|
||||
|
||||
return reducedString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ namespace Umbraco.Core.IO
|
||||
/// A custom file system provider for media
|
||||
/// </summary>
|
||||
[FileSystemProvider("media")]
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
internal class MediaFileSystem : FileSystemWrapper
|
||||
public class MediaFileSystem : FileSystemWrapper
|
||||
{
|
||||
public MediaFileSystem(IFileSystem wrapped)
|
||||
: base(wrapped)
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
|
||||
[UmbracoExperimentalFeature("http://issues.umbraco.org/issue/U4-1156", "Will be declared public after 4.10")]
|
||||
internal class PhysicalFileSystem : IFileSystem
|
||||
public class PhysicalFileSystem : IFileSystem
|
||||
{
|
||||
private readonly string _rootPath;
|
||||
private readonly string _rootUrl;
|
||||
|
||||
public PhysicalFileSystem(string virtualRoot)
|
||||
{
|
||||
_rootPath = System.Web.Hosting.HostingEnvironment.MapPath(virtualRoot);
|
||||
_rootUrl = VirtualPathUtility.ToAbsolute(virtualRoot);
|
||||
_rootPath = IOHelper.MapPath(virtualRoot);
|
||||
_rootUrl = IOHelper.ResolveUrl(virtualRoot);
|
||||
}
|
||||
|
||||
public PhysicalFileSystem(string rootPath, string rootUrl)
|
||||
@@ -43,9 +42,13 @@ namespace Umbraco.Core.IO
|
||||
return Directory.EnumerateDirectories(path).Select(GetRelativePath);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{ }
|
||||
{
|
||||
LogHelper.Error<PhysicalFileSystem>("Not authorized to get directories", ex);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{ }
|
||||
{
|
||||
LogHelper.Error<PhysicalFileSystem>("Directory not found", ex);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
@@ -65,7 +68,9 @@ namespace Umbraco.Core.IO
|
||||
Directory.Delete(GetFullPath(path), recursive);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{ }
|
||||
{
|
||||
LogHelper.Error<PhysicalFileSystem>("Directory not found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string path)
|
||||
@@ -80,9 +85,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public void AddFile(string path, Stream stream, bool overrideIfExists)
|
||||
{
|
||||
if (FileExists(path) && !overrideIfExists)
|
||||
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists",
|
||||
path));
|
||||
if (FileExists(path) && !overrideIfExists) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
|
||||
|
||||
EnsureDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
@@ -108,9 +111,13 @@ namespace Umbraco.Core.IO
|
||||
return Directory.EnumerateFiles(path, filter).Select(GetRelativePath);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{ }
|
||||
{
|
||||
LogHelper.Error<PhysicalFileSystem>("Not authorized to get directories", ex);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{ }
|
||||
{
|
||||
LogHelper.Error<PhysicalFileSystem>("Directory not found", ex);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
@@ -130,7 +137,9 @@ namespace Umbraco.Core.IO
|
||||
File.Delete(GetFullPath(path));
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{ }
|
||||
{
|
||||
LogHelper.Error<PhysicalFileSystem>("File not found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool FileExists(string path)
|
||||
@@ -188,7 +197,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
protected string EnsureTrailingSeparator(string path)
|
||||
{
|
||||
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
|
||||
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal))
|
||||
path = path + Path.DirectorySeparatorChar;
|
||||
|
||||
return path;
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Umbraco.Core.IO
|
||||
//all paths has a starting but no trailing /
|
||||
public class SystemDirectories
|
||||
{
|
||||
//TODO: Why on earth is this even configurable? You cannot change the /Bin folder in ASP.Net
|
||||
public static string Bin
|
||||
{
|
||||
get
|
||||
@@ -68,6 +69,15 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
}
|
||||
|
||||
public static string AppPlugins
|
||||
{
|
||||
get
|
||||
{
|
||||
//NOTE: this is not configurable and shouldn't need to be
|
||||
return "~/App_Plugins";
|
||||
}
|
||||
}
|
||||
|
||||
public static string MvcViews
|
||||
{
|
||||
get
|
||||
@@ -173,16 +183,26 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
}
|
||||
|
||||
private static string _root;
|
||||
/// <summary>
|
||||
/// Gets the root path of the application
|
||||
/// </summary>
|
||||
public static string Root
|
||||
{
|
||||
get
|
||||
{
|
||||
string appPath = HttpRuntime.AppDomainAppVirtualPath ?? string.Empty;
|
||||
if (appPath == "/")
|
||||
appPath = string.Empty;
|
||||
if (_root == null)
|
||||
{
|
||||
string appPath = HttpRuntime.AppDomainAppVirtualPath ?? string.Empty;
|
||||
if (appPath == "/")
|
||||
appPath = string.Empty;
|
||||
|
||||
return appPath;
|
||||
_root = appPath;
|
||||
}
|
||||
return _root;
|
||||
}
|
||||
//Only required for unit tests
|
||||
internal set { _root = value; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,23 +64,28 @@ namespace Umbraco.Core.Logging
|
||||
{
|
||||
_forceStop = true;
|
||||
var windowsIdentity = WindowsIdentity.GetCurrent();
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = Level.Error,
|
||||
Message =
|
||||
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = "",
|
||||
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo =
|
||||
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
})
|
||||
);
|
||||
|
||||
var logEvent = new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = global::log4net.Core.Level.Error,
|
||||
Message =
|
||||
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = "",
|
||||
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo =
|
||||
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
});
|
||||
|
||||
if (this.DateTimeStrategy != null)
|
||||
{
|
||||
base.Append(logEvent);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnClose();
|
||||
|
||||
@@ -60,49 +60,77 @@ namespace Umbraco.Core.Logging
|
||||
|
||||
#region Warn
|
||||
|
||||
public static void Warn(Type callingType, string message, params object[] format)
|
||||
public static void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.WarnFormat(PrefixThreadId(message), format);
|
||||
if (logger == null || !logger.IsWarnEnabled) return;
|
||||
logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray());
|
||||
}
|
||||
|
||||
public static void Warn(Type callingType, TraceContext trace, string message, params object[] format)
|
||||
public static void Warn(Type callingType, string message, bool showHttpTrace, params Func<object>[] formatItems)
|
||||
{
|
||||
if (trace != null)
|
||||
Mandate.ParameterNotNull(callingType, "callingType");
|
||||
Mandate.ParameterNotNullOrEmpty(message, "message");
|
||||
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
{
|
||||
trace.Warn(string.Format(message, format));
|
||||
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
|
||||
}
|
||||
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.WarnFormat(PrefixThreadId(message), format);
|
||||
if (logger == null || !logger.IsWarnEnabled) return;
|
||||
logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray());
|
||||
|
||||
}
|
||||
|
||||
public static void WarnWithException(Type callingType, string message, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
WarnWithException(callingType, message, false, e, formatItems);
|
||||
}
|
||||
|
||||
public static void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
Mandate.ParameterNotNull(e, "e");
|
||||
Mandate.ParameterNotNull(callingType, "callingType");
|
||||
Mandate.ParameterNotNullOrEmpty(message, "message");
|
||||
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn(
|
||||
callingType.Name,
|
||||
string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()),
|
||||
e);
|
||||
}
|
||||
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsWarnEnabled) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a warn log
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="items"></param>
|
||||
public static void Warn<T>(string message, params object[] items)
|
||||
/// <param name="formatItems"></param>
|
||||
public static void Warn<T>(string message, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LoggerFor<T>();
|
||||
if (logger != null)
|
||||
logger.WarnFormat(PrefixThreadId(message), items);
|
||||
Warn(typeof(T), message, formatItems);
|
||||
}
|
||||
|
||||
public static void Warn<T>(string message, TraceContext trace, params object[] items)
|
||||
public static void Warn<T>(string message, bool showHttpTrace, params Func<object>[] formatItems)
|
||||
{
|
||||
if (trace != null)
|
||||
{
|
||||
trace.Warn(string.Format(message, items));
|
||||
}
|
||||
Warn(typeof(T), message, showHttpTrace, formatItems);
|
||||
}
|
||||
|
||||
var logger = LoggerFor<T>();
|
||||
if (logger != null)
|
||||
logger.WarnFormat(PrefixThreadId(message), items);
|
||||
public static void WarnWithException<T>(string message, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
WarnWithException(typeof(T), message, e, formatItems);
|
||||
}
|
||||
public static void WarnWithException<T>(string message, bool showHttpTrace, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
WarnWithException(typeof(T), message, showHttpTrace, e, formatItems);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -214,13 +242,15 @@ namespace Umbraco.Core.Logging
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="generateMessageFormat"></param>
|
||||
/// <param name="trace"></param>
|
||||
/// <param name="showHttpTrace"></param>
|
||||
/// <param name="formatItems"></param>
|
||||
public static void Debug<T>(string generateMessageFormat, TraceContext trace, params Func<object>[] formatItems)
|
||||
public static void Debug<T>(string generateMessageFormat, bool showHttpTrace, params Func<object>[] formatItems)
|
||||
{
|
||||
if (trace != null)
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
{
|
||||
trace.Write(string.Format(generateMessageFormat, formatItems.Select(x => x())));
|
||||
HttpContext.Current.Trace.Write(
|
||||
typeof(T).Name,
|
||||
string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray()));
|
||||
}
|
||||
Debug(typeof(T), generateMessageFormat, formatItems);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public enum MacroErrorBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Default umbraco behavior - show an inline error within the
|
||||
/// macro but allow the page to continue rendering.
|
||||
/// </summary>
|
||||
Inline,
|
||||
|
||||
/// <summary>
|
||||
/// Silently eat the error and do not display the offending macro.
|
||||
/// </summary>
|
||||
Silent,
|
||||
|
||||
/// <summary>
|
||||
/// Throw an exception which can be caught by the global error handler
|
||||
/// defined in Application_OnError. If no such error handler is defined
|
||||
/// then you'll see the Yellow Screen Of Death (YSOD) error page.
|
||||
/// </summary>
|
||||
Throw
|
||||
}
|
||||
}
|
||||
@@ -66,8 +66,7 @@ namespace Umbraco.Core.Macros
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var macroAlias = attributes["macroalias"] ?? attributes["alias"];
|
||||
var macroAlias = attributes.ContainsKey("macroalias") ? attributes["macroalias"] : attributes["alias"];
|
||||
|
||||
//call the callback now that we have the macro parsed
|
||||
macroFoundCallback(macroAlias, attributes);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public interface IImageUrlProvider
|
||||
{
|
||||
string Name { get; }
|
||||
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
|
||||
string GetImageUrlFromFileName(string specifiedSrc, IDictionary<string, string> parameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for lazily resolving types for a resolver
|
||||
/// </summary>
|
||||
/// <typeparam name="TResolver"></typeparam>
|
||||
/// <typeparam name="TResolved"></typeparam>
|
||||
/// <remarks>
|
||||
/// This is a special case resolver for when types get lazily resolved in order to resolve the actual types. This is useful
|
||||
/// for when there is some processing overhead (i.e. Type finding in assemblies) to return the Types used to instantiate the instances.
|
||||
/// In some these cases we don't want to have to type find during application startup, only when we need to resolve the instances.
|
||||
///
|
||||
/// Important notes about this resolver: This does not support Insert or Remove and therefore does not support any ordering unless
|
||||
/// the types are marked with the WeightedPluginAttribute.
|
||||
/// </remarks>
|
||||
internal abstract class LazyManyObjectsResolverBase<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
|
||||
where TResolved : class
|
||||
where TResolver : class
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
protected LazyManyObjectsResolverBase(ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: base(scope)
|
||||
{
|
||||
}
|
||||
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext)
|
||||
: base(httpContext)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a list of lazy types
|
||||
/// </summary>
|
||||
/// <param name="listOfLazyTypes"></param>
|
||||
/// <param name="scope"></param>
|
||||
protected LazyManyObjectsResolverBase(IEnumerable<Lazy<Type>> listOfLazyTypes, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
AddTypes(listOfLazyTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a delegate to return a list of types
|
||||
/// </summary>
|
||||
/// <param name="typeListDelegate"></param>
|
||||
/// <param name="scope"></param>
|
||||
protected LazyManyObjectsResolverBase(Func<IEnumerable<Type>> typeListDelegate, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
_listOfTypeListDelegates.Add(typeListDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a list of lazy types
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <param name="listOfLazyTypes"></param>
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Lazy<Type>> listOfLazyTypes)
|
||||
: this(httpContext)
|
||||
{
|
||||
AddTypes(listOfLazyTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a delegate to return a list of types
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <param name="typeListDelegate"></param>
|
||||
protected LazyManyObjectsResolverBase(HttpContextBase httpContext, Func<IEnumerable<Type>> typeListDelegate)
|
||||
: this(httpContext)
|
||||
{
|
||||
_listOfTypeListDelegates.Add(typeListDelegate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly List<Lazy<Type>> _lazyTypeList = new List<Lazy<Type>>();
|
||||
private readonly List<Func<IEnumerable<Type>>> _listOfTypeListDelegates = new List<Func<IEnumerable<Type>>>();
|
||||
private List<Type> _resolvedTypes = null;
|
||||
private readonly ReaderWriterLockSlim _typeResolutionLock = new ReaderWriterLockSlim();
|
||||
|
||||
/// <summary>
|
||||
/// Used for unit tests
|
||||
/// </summary>
|
||||
internal bool HasResolvedTypes
|
||||
{
|
||||
get { return _resolvedTypes != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Once this is called this will resolve all types registered in the lazy list
|
||||
/// </summary>
|
||||
protected override IEnumerable<Type> InstanceTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
using (var lck = new UpgradeableReadLock(_typeResolutionLock))
|
||||
{
|
||||
var lazyTypeList = _lazyTypeList.Select(x => x.Value).ToArray();
|
||||
var listofTypeListDelegates = _listOfTypeListDelegates.SelectMany(x => x()).ToArray();
|
||||
|
||||
//we need to validate each resolved type now since we could not do it before when inserting the lazy delegates
|
||||
if (!HasResolvedTypes)
|
||||
{
|
||||
lck.UpgradeToWriteLock();
|
||||
|
||||
_resolvedTypes = new List<Type>();
|
||||
|
||||
//first iterate the lazy type list
|
||||
foreach (var l in lazyTypeList)
|
||||
{
|
||||
UpdateUniqueList(_resolvedTypes, l);
|
||||
}
|
||||
|
||||
//next iterate the list of list type delegates
|
||||
foreach (var l in listofTypeListDelegates)
|
||||
{
|
||||
UpdateUniqueList(_resolvedTypes, l);
|
||||
}
|
||||
}
|
||||
|
||||
return _resolvedTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUniqueList(List<Type> uniqueList, Type toAdd)
|
||||
{
|
||||
EnsureCorrectType(toAdd);
|
||||
if (uniqueList.Contains(toAdd))
|
||||
{
|
||||
throw new InvalidOperationException("The Type " + toAdd + " already exists in the collection");
|
||||
}
|
||||
uniqueList.Add(toAdd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows adding of multiple lazy types at once
|
||||
/// </summary>
|
||||
/// <param name="types"></param>
|
||||
protected void AddTypes(IEnumerable<Lazy<Type>> types)
|
||||
{
|
||||
EnsureAddSupport();
|
||||
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
foreach (var t in types)
|
||||
{
|
||||
_lazyTypeList.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type list delegate to the collection
|
||||
/// </summary>
|
||||
/// <param name="typeListDelegate"></param>
|
||||
public void AddTypeListDelegate(Func<IEnumerable<Type>> typeListDelegate)
|
||||
{
|
||||
EnsureAddSupport();
|
||||
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
_listOfTypeListDelegates.Add(typeListDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a lazy type to the list
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void AddType(Lazy<Type> value)
|
||||
{
|
||||
EnsureAddSupport();
|
||||
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
_lazyTypeList.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the static type added to a lazy type and adds it to the internal list
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void AddType(Type value)
|
||||
{
|
||||
AddType(new Lazy<Type>(() => value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all lazy types
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
EnsureClearSupport();
|
||||
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
_lazyTypeList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does not support removal
|
||||
/// </summary>
|
||||
protected override bool SupportsRemove
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does not support insert
|
||||
/// </summary>
|
||||
protected override bool SupportsInsert
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// these old classes don't contain metadata, the objects need to be instantiated first to get their metadata, we then store this
|
||||
/// for use in the GetById method.
|
||||
/// </remarks>
|
||||
internal abstract class LegacyTransientObjectsResolver<TResolver, TResolved> : ManyObjectsResolverBase<TResolver, TResolved>
|
||||
internal abstract class LegacyTransientObjectsResolver<TResolver, TResolved> : LazyManyObjectsResolverBase<TResolver, TResolved>
|
||||
where TResolved : class
|
||||
where TResolver : class
|
||||
{
|
||||
@@ -27,16 +27,15 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="refreshers"></param>
|
||||
/// <param name="types"></param>
|
||||
/// <remarks>
|
||||
/// We are creating Transient instances (new instances each time) because this is how the legacy code worked and
|
||||
/// I don't want to muck anything up by changing them to application based instances.
|
||||
/// TODO: However, it would make much more sense to do this and would speed up the application plus this would make the GetById method much easier.
|
||||
/// </remarks>
|
||||
protected LegacyTransientObjectsResolver(IEnumerable<Type> refreshers)
|
||||
: base(ObjectLifetimeScope.Transient) // new objects every time
|
||||
{
|
||||
AddTypes(refreshers);
|
||||
protected LegacyTransientObjectsResolver(Func<IEnumerable<Type>> types)
|
||||
: base(types, ObjectLifetimeScope.Transient) // new objects every time
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -55,7 +54,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
protected abstract Guid GetUniqueIdentifier(TResolved obj);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new ICacheRefresher instance by id
|
||||
/// Returns a new TResolved instance by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using Umbraco.Core.Macros;
|
||||
using umbraco.interfaces;
|
||||
@@ -13,14 +15,14 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Much of this classes methods are based on legacy code from umbraco.editorControls.macrocontainer.MacroControlFactory
|
||||
/// this code should probably be reviewed and cleaned up if necessary.
|
||||
/// </remarks>
|
||||
internal sealed class MacroFieldEditorsResolver : ManyObjectsResolverBase<MacroFieldEditorsResolver, IMacroGuiRendering>
|
||||
internal sealed class MacroFieldEditorsResolver : LazyManyObjectsResolverBase<MacroFieldEditorsResolver, IMacroGuiRendering>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="macroEditors"></param>
|
||||
internal MacroFieldEditorsResolver(IEnumerable<Type> macroEditors)
|
||||
internal MacroFieldEditorsResolver(Func<IEnumerable<Type>> macroEditors)
|
||||
: base(macroEditors, ObjectLifetimeScope.Transient)
|
||||
{
|
||||
|
||||
@@ -47,7 +49,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </remarks>
|
||||
internal string GetValueFromMacroControl(Control macroControl)
|
||||
{
|
||||
return ((IMacroGuiRendering)macroControl).Value;
|
||||
return HttpUtility.HtmlDecode(((IMacroGuiRendering)macroControl).Value);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
@@ -55,7 +57,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </remarks>
|
||||
internal List<Type> MacroControlTypes
|
||||
{
|
||||
get { return InstanceTypes; }
|
||||
get { return InstanceTypes.ToList(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -74,7 +76,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
if (!string.IsNullOrEmpty(prop.Value))
|
||||
{
|
||||
instance.Value = prop.Value;
|
||||
instance.Value = HttpUtility.HtmlDecode(prop.Value);
|
||||
}
|
||||
var macroControl = instance as Control;
|
||||
if (macroControl != null)
|
||||
|
||||
@@ -6,14 +6,14 @@ using System.Web;
|
||||
|
||||
namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
|
||||
internal abstract class ManyObjectsResolverBase<TResolver, TResolved> : ResolverBase<TResolver>
|
||||
where TResolved : class
|
||||
where TResolver : class
|
||||
{
|
||||
private List<TResolved> _applicationInstances = null;
|
||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
|
||||
private readonly List<Type> _instanceTypes = new List<Type>();
|
||||
|
||||
#region Constructors
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
}
|
||||
|
||||
LifetimeScope = scope;
|
||||
InstanceTypes = new List<Type>();
|
||||
_instanceTypes = new List<Type>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -48,7 +48,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
||||
CurrentHttpContext = httpContext;
|
||||
InstanceTypes = new List<Type>();
|
||||
_instanceTypes = new List<Type>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,8 +58,8 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <param name="scope">If set to true will resolve singleton objects which will be created once for the lifetime of the application</param>
|
||||
protected ManyObjectsResolverBase(IEnumerable<Type> value, ObjectLifetimeScope scope = ObjectLifetimeScope.Application)
|
||||
: this(scope)
|
||||
{
|
||||
InstanceTypes = new List<Type>(value);
|
||||
{
|
||||
_instanceTypes = new List<Type>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -71,7 +71,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
protected ManyObjectsResolverBase(HttpContextBase httpContext, IEnumerable<Type> value)
|
||||
: this(httpContext)
|
||||
{
|
||||
InstanceTypes = new List<Type>(value);
|
||||
_instanceTypes = new List<Type>(value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -83,7 +83,10 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Returns the list of Types registered that instances will be created from
|
||||
/// </summary>
|
||||
protected List<Type> InstanceTypes { get; private set; }
|
||||
protected virtual IEnumerable<Type> InstanceTypes
|
||||
{
|
||||
get { return _instanceTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Current HttpContextBase used to construct this object if one exists.
|
||||
@@ -97,11 +100,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
protected ObjectLifetimeScope LifetimeScope { get; private set; }
|
||||
|
||||
private int _defaultPluginWeight = 10;
|
||||
private bool _supportsAdd = true;
|
||||
private bool _supportsInsert = true;
|
||||
private bool _supportsClear = true;
|
||||
private bool _supportsRemove = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used in conjunction with GetSortedValues and WeightedPluginAttribute, if any of the objects
|
||||
/// being resolved do not contain the WeightedPluginAttribute then this will be the default weight applied
|
||||
@@ -189,15 +188,16 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to remove.</param>
|
||||
public void RemoveType(Type value)
|
||||
public virtual void RemoveType(Type value)
|
||||
{
|
||||
if (!SupportsRemove)
|
||||
throw new InvalidOperationException("This resolver does not support Removing types");
|
||||
EnsureRemoveSupport();
|
||||
|
||||
using (new WriteLock(_lock))
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
EnsureCorrectType(value);
|
||||
InstanceTypes.Remove(value);
|
||||
_instanceTypes.Remove(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,8 +215,12 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="types"></param>
|
||||
protected void AddTypes(IEnumerable<Type> types)
|
||||
{
|
||||
using (var l = new WriteLock(_lock))
|
||||
{
|
||||
EnsureAddSupport();
|
||||
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
foreach(var t in types)
|
||||
{
|
||||
@@ -225,7 +229,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
{
|
||||
throw new InvalidOperationException("The Type " + t + " already exists in the collection");
|
||||
};
|
||||
InstanceTypes.Add(t);
|
||||
_instanceTypes.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,19 +238,20 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Adds a Type to the end of the list.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to be added.</param>
|
||||
public void AddType(Type value)
|
||||
public virtual void AddType(Type value)
|
||||
{
|
||||
if (!SupportsAdd)
|
||||
throw new InvalidOperationException("This resolver does not support Adding new types");
|
||||
EnsureAddSupport();
|
||||
|
||||
using (var l = new WriteLock(_lock))
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
EnsureCorrectType(value);
|
||||
if (InstanceTypes.Contains(value))
|
||||
{
|
||||
throw new InvalidOperationException("The Type " + value + " already exists in the collection");
|
||||
};
|
||||
InstanceTypes.Add(value);
|
||||
_instanceTypes.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,14 +267,15 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Clears the list.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
public virtual void Clear()
|
||||
{
|
||||
if (!SupportsClear)
|
||||
throw new InvalidOperationException("This resolver does not support Clearing types");
|
||||
EnsureClearSupport();
|
||||
|
||||
using (new WriteLock(_lock))
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (GetWriteLock())
|
||||
{
|
||||
InstanceTypes.Clear();
|
||||
_instanceTypes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,12 +284,13 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the object should be inserted.</param>
|
||||
/// <param name="value">The object to insert.</param>
|
||||
public void InsertType(int index, Type value)
|
||||
public virtual void InsertType(int index, Type value)
|
||||
{
|
||||
if (!SupportsInsert)
|
||||
throw new InvalidOperationException("This resolver does not support Inserting new types");
|
||||
EnsureInsertSupport();
|
||||
|
||||
using (var l = new UpgradeableReadLock(_lock))
|
||||
EnsureResolutionNotFrozen();
|
||||
|
||||
using (var l = GetWriteLock())
|
||||
{
|
||||
EnsureCorrectType(value);
|
||||
if (InstanceTypes.Contains(value))
|
||||
@@ -291,8 +298,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
throw new InvalidOperationException("The Type " + value + " already exists in the collection");
|
||||
};
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
InstanceTypes.Insert(index, value);
|
||||
_instanceTypes.Insert(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +312,65 @@ namespace Umbraco.Core.ObjectResolution
|
||||
InsertType(index, typeof (T));
|
||||
}
|
||||
|
||||
private void EnsureCorrectType(Type t)
|
||||
/// <summary>
|
||||
/// Returns a WriteLock to use when modifying collections
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected WriteLock GetWriteLock()
|
||||
{
|
||||
return new WriteLock(_lock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if resolution is frozen
|
||||
/// </summary>
|
||||
protected void EnsureResolutionNotFrozen()
|
||||
{
|
||||
if (Resolution.IsFrozen)
|
||||
throw new InvalidOperationException("The type list cannot be modified after resolution has been frozen");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if this does not support Remove
|
||||
/// </summary>
|
||||
protected void EnsureRemoveSupport()
|
||||
{
|
||||
if (!SupportsRemove)
|
||||
throw new InvalidOperationException("This resolver does not support Removing types");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if this does not support Clear
|
||||
/// </summary>
|
||||
protected void EnsureClearSupport()
|
||||
{
|
||||
if (!SupportsClear)
|
||||
throw new InvalidOperationException("This resolver does not support Clearing types");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if this does not support Add
|
||||
/// </summary>
|
||||
protected void EnsureAddSupport()
|
||||
{
|
||||
if (!SupportsAdd)
|
||||
throw new InvalidOperationException("This resolver does not support Adding new types");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if this does not support insert
|
||||
/// </summary>
|
||||
protected void EnsureInsertSupport()
|
||||
{
|
||||
if (!SupportsInsert)
|
||||
throw new InvalidOperationException("This resolver does not support Inserting new types");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if the type is not of the TResolved type
|
||||
/// </summary>
|
||||
/// <param name="t"></param>
|
||||
protected void EnsureCorrectType(Type t)
|
||||
{
|
||||
if (!TypeHelper.IsTypeAssignableFrom<TResolved>(t))
|
||||
throw new InvalidOperationException("The resolver " + this.GetType() + " can only accept types of " + typeof(TResolved) + ". The Type passed in to this method is " + t);
|
||||
@@ -314,22 +378,22 @@ namespace Umbraco.Core.ObjectResolution
|
||||
|
||||
protected virtual bool SupportsAdd
|
||||
{
|
||||
get { return _supportsAdd; }
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected virtual bool SupportsInsert
|
||||
{
|
||||
get { return _supportsInsert; }
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected virtual bool SupportsClear
|
||||
{
|
||||
get { return _supportsClear; }
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected virtual bool SupportsRemove
|
||||
{
|
||||
get { return _supportsRemove; }
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,14 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// A resolver to return all IPackageAction objects
|
||||
/// </summary>
|
||||
internal sealed class PackageActionsResolver : ManyObjectsResolverBase<PackageActionsResolver, IPackageAction>
|
||||
internal sealed class PackageActionsResolver : LazyManyObjectsResolverBase<PackageActionsResolver, IPackageAction>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="packageActions"></param>
|
||||
internal PackageActionsResolver(IEnumerable<Type> packageActions)
|
||||
internal PackageActionsResolver(Func<IEnumerable<Type>> packageActions)
|
||||
: base(packageActions)
|
||||
{
|
||||
|
||||
|
||||
+710
-290
File diff suppressed because it is too large
Load Diff
@@ -21,16 +21,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <returns></returns>
|
||||
public Attempt<object> ConvertPropertyValue(object value)
|
||||
{
|
||||
if (value == null) return new Attempt<object>(false, null);
|
||||
//if its already a DateTime
|
||||
if (TypeHelper.IsTypeAssignableFrom<DateTime>(value))
|
||||
return new Attempt<object>(true, value);
|
||||
//convert to string
|
||||
var asString = Convert.ToString(value);
|
||||
DateTime dt;
|
||||
return DateTime.TryParse(asString, out dt)
|
||||
? new Attempt<object>(true, dt)
|
||||
: new Attempt<object>(false, null);
|
||||
return value.TryConvertTo(typeof(DateTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <summary>
|
||||
/// Manages the list of IPropertyEditorValueConverter's
|
||||
/// </summary>
|
||||
internal class PropertyEditorValueConvertersResolver : ManyObjectsResolverBase<PropertyEditorValueConvertersResolver, IPropertyEditorValueConverter>
|
||||
internal sealed class PropertyEditorValueConvertersResolver : ManyObjectsResolverBase<PropertyEditorValueConvertersResolver, IPropertyEditorValueConverter>
|
||||
{
|
||||
public PropertyEditorValueConvertersResolver(IEnumerable<Type> converters)
|
||||
: base(converters)
|
||||
|
||||
@@ -16,18 +16,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <returns></returns>
|
||||
public Attempt<object> ConvertPropertyValue(object value)
|
||||
{
|
||||
if (value == null) return new Attempt<object>(false, null);
|
||||
//if its already a bool
|
||||
if (TypeHelper.IsTypeAssignableFrom<bool>(value))
|
||||
return new Attempt<object>(true, value);
|
||||
//convert to string
|
||||
var asString = Convert.ToString(value);
|
||||
bool asBool;
|
||||
return bool.TryParse(asString, out asBool)
|
||||
? new Attempt<object>(true, asBool)
|
||||
: bool.TryParse(asString.Replace("1", "true").Replace("0", "false"), out asBool) //convert 0 or 1 to true or false
|
||||
? new Attempt<object>(true, asBool)
|
||||
: new Attempt<object>(false, null);
|
||||
return value.TryConvertTo(typeof(bool));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.Models;
|
||||
using umbraco.interfaces;
|
||||
|
||||
@@ -14,6 +13,7 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class PublishedContentExtensions
|
||||
{
|
||||
|
||||
|
||||
|
||||
#region GetProperty
|
||||
@@ -41,24 +41,33 @@ namespace Umbraco.Core
|
||||
#endregion
|
||||
|
||||
#region GetPropertyValue
|
||||
public static string GetPropertyValue(this IPublishedContent doc, string alias)
|
||||
public static object GetPropertyValue(this IPublishedContent doc, string alias)
|
||||
{
|
||||
return doc.GetPropertyValue(alias, false);
|
||||
}
|
||||
public static string GetPropertyValue(this IPublishedContent doc, string alias, string fallback)
|
||||
public static object GetPropertyValue(this IPublishedContent doc, string alias, string fallback)
|
||||
{
|
||||
var prop = doc.GetPropertyValue(alias);
|
||||
return !prop.IsNullOrWhiteSpace() ? prop : fallback;
|
||||
return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback;
|
||||
}
|
||||
public static string GetPropertyValue(this IPublishedContent doc, string alias, bool recursive)
|
||||
public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive)
|
||||
{
|
||||
var p = doc.GetProperty(alias, recursive);
|
||||
return p == null ? null : Convert.ToString(p.Value);
|
||||
if (p == null) return null;
|
||||
|
||||
//Here we need to put the value through the IPropertyEditorValueConverter's
|
||||
//get the data type id for the current property
|
||||
var dataType = PublishedContentHelper.GetDataType(doc.DocumentTypeAlias, alias);
|
||||
//convert the string value to a known type
|
||||
var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, doc.DocumentTypeAlias, alias);
|
||||
return converted.Success
|
||||
? converted.Result
|
||||
: p.Value;
|
||||
}
|
||||
public static string GetPropertyValue(this IPublishedContent doc, string alias, bool recursive, string fallback)
|
||||
public static object GetPropertyValue(this IPublishedContent doc, string alias, bool recursive, string fallback)
|
||||
{
|
||||
var prop = doc.GetPropertyValue(alias, recursive);
|
||||
return !prop.IsNullOrWhiteSpace() ? prop : fallback;
|
||||
return (prop != null && !Convert.ToString(prop).IsNullOrWhiteSpace()) ? prop : fallback;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -125,23 +134,51 @@ namespace Umbraco.Core
|
||||
/// then the default value of type T is returned.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="prop"></param>
|
||||
/// <param name="doc"></param>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetPropertyValue<T>(this IPublishedContent prop, string alias)
|
||||
public static T GetPropertyValue<T>(this IPublishedContent doc, string alias)
|
||||
{
|
||||
return prop.GetPropertyValue<T>(alias, default(T));
|
||||
return doc.GetPropertyValue<T>(alias, default(T));
|
||||
}
|
||||
|
||||
public static T GetPropertyValue<T>(this IPublishedContent prop, string alias, bool recursive, T ifCannotConvert)
|
||||
{
|
||||
var p = prop.GetProperty(alias, recursive);
|
||||
if (p == null)
|
||||
return ifCannotConvert;
|
||||
|
||||
//before we try to convert it manually, lets see if the PropertyEditorValueConverter does this for us
|
||||
//Here we need to put the value through the IPropertyEditorValueConverter's
|
||||
//get the data type id for the current property
|
||||
var dataType = PublishedContentHelper.GetDataType(prop.DocumentTypeAlias, alias);
|
||||
//convert the value to a known type
|
||||
var converted = PublishedContentHelper.ConvertPropertyValue(p.Value, dataType, prop.DocumentTypeAlias, alias);
|
||||
if (converted.Success)
|
||||
{
|
||||
//if its successful, check if its the correct type and return it
|
||||
if (converted.Result is T)
|
||||
{
|
||||
return (T)converted.Result;
|
||||
}
|
||||
//if that's not correct, try converting the converted type
|
||||
var reConverted = converted.Result.TryConvertTo<T>();
|
||||
if (reConverted.Success)
|
||||
{
|
||||
return reConverted.Result;
|
||||
}
|
||||
}
|
||||
|
||||
//last, if all the above has failed, we'll just try converting the raw value straight to 'T'
|
||||
var manualConverted = p.Value.TryConvertTo<T>();
|
||||
if (manualConverted.Success)
|
||||
return manualConverted.Result;
|
||||
return ifCannotConvert;
|
||||
}
|
||||
|
||||
public static T GetPropertyValue<T>(this IPublishedContent prop, string alias, T ifCannotConvert)
|
||||
{
|
||||
var p = prop.GetProperty(alias);
|
||||
if (p == null)
|
||||
return default(T);
|
||||
var converted = p.Value.TryConvertTo<T>();
|
||||
if (converted.Success)
|
||||
return converted.Result;
|
||||
return ifCannotConvert;
|
||||
return prop.GetPropertyValue<T>(alias, false, ifCannotConvert);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
internal class PublishedContentHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// This callback is used only so we can set it dynamically because in the "Core" project currently we don't have
|
||||
/// access to the business logic layer.
|
||||
/// TODO: Once 6.0 is released we need to change this to use the new business logic layer that we can access from
|
||||
/// this proejct. Until then this will return a Guid.Empty but the callback will need to be set in the WebBootManager
|
||||
/// to work in the website. if people use this in a non-web aspect without the WebBootManager, the the IPropertyEditorValueConverters
|
||||
/// will not be executed.
|
||||
/// </summary>
|
||||
internal static Func<string, string, Guid> GetDataTypeCallback = (docTypeAlias, propertyAlias) => Guid.Empty;
|
||||
|
||||
internal static Guid GetDataType(string docTypeAlias, string propertyAlias)
|
||||
{
|
||||
return GetDataTypeCallback(docTypeAlias, propertyAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the currentValue to a correctly typed value based on known registered converters, then based on known standards.
|
||||
/// </summary>
|
||||
/// <param name="currentValue"></param>
|
||||
/// <param name="dataType"></param>
|
||||
/// <param name="docTypeAlias"></param>
|
||||
/// <param name="propertyTypeAlias"></param>
|
||||
/// <returns></returns>
|
||||
internal static Attempt<object> ConvertPropertyValue(object currentValue, Guid dataType, string docTypeAlias, string propertyTypeAlias)
|
||||
{
|
||||
if (currentValue == null) return Attempt<object>.False;
|
||||
|
||||
//First lets check all registered converters for this data type.
|
||||
var converters = PropertyEditorValueConvertersResolver.Current.Converters
|
||||
.Where(x => x.IsConverterFor(dataType, docTypeAlias, propertyTypeAlias))
|
||||
.ToArray();
|
||||
|
||||
//try to convert the value with any of the converters:
|
||||
foreach (var converted in converters
|
||||
.Select(p => p.ConvertPropertyValue(currentValue))
|
||||
.Where(converted => converted.Success))
|
||||
{
|
||||
return new Attempt<object>(true, converted.Result);
|
||||
}
|
||||
|
||||
//if none of the converters worked, then we'll process this from what we know
|
||||
|
||||
var sResult = Convert.ToString(currentValue).Trim();
|
||||
|
||||
//this will eat csv strings, so only do it if the decimal also includes a decimal seperator (according to the current culture)
|
||||
if (sResult.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator))
|
||||
{
|
||||
decimal dResult;
|
||||
if (decimal.TryParse(sResult, System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.CurrentCulture, out dResult))
|
||||
{
|
||||
return new Attempt<object>(true, dResult);
|
||||
}
|
||||
}
|
||||
//process string booleans as booleans
|
||||
if (sResult.InvariantEquals("true"))
|
||||
{
|
||||
return new Attempt<object>(true, true);
|
||||
}
|
||||
if (sResult.InvariantEquals("false"))
|
||||
{
|
||||
return new Attempt<object>(true, false);
|
||||
}
|
||||
|
||||
//a really rough check to see if this may be valid xml
|
||||
//TODO: This is legacy code, I'm sure there's a better and nicer way
|
||||
if (sResult.StartsWith("<") && sResult.EndsWith(">") && sResult.Contains("/"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var e = XElement.Parse(DynamicXml.StripDashesInElementOrAttributeNames(sResult), LoadOptions.None);
|
||||
|
||||
//check that the document element is not one of the disallowed elements
|
||||
//allows RTE to still return as html if it's valid xhtml
|
||||
var documentElement = e.Name.LocalName;
|
||||
|
||||
//TODO: See note against this setting, pretty sure we don't need this
|
||||
if (!UmbracoSettings.NotDynamicXmlDocumentElements.Any(
|
||||
tag => string.Equals(tag, documentElement, StringComparison.CurrentCultureIgnoreCase)))
|
||||
{
|
||||
return new Attempt<object>(true, new DynamicXml(e));
|
||||
}
|
||||
return Attempt<object>.False;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Attempt<object>.False;
|
||||
}
|
||||
}
|
||||
return Attempt<object>.False;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -18,6 +19,65 @@ namespace Umbraco.Core
|
||||
///</summary>
|
||||
public static class StringExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Encrypt the string using the MachineKey in medium trust
|
||||
/// </summary>
|
||||
/// <param name="value">The string value to be encrypted.</param>
|
||||
/// <returns></returns>
|
||||
public static string EncryptWithMachineKey(this string value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
string valueToEncrypt = value;
|
||||
List<string> parts = new List<string>();
|
||||
|
||||
const int EncrpytBlockSize = 500;
|
||||
|
||||
while (valueToEncrypt.Length > EncrpytBlockSize)
|
||||
{
|
||||
parts.Add(valueToEncrypt.Substring(0, EncrpytBlockSize));
|
||||
valueToEncrypt = valueToEncrypt.Remove(0, EncrpytBlockSize);
|
||||
}
|
||||
|
||||
if (valueToEncrypt.Length > 0)
|
||||
{
|
||||
parts.Add(valueToEncrypt);
|
||||
}
|
||||
|
||||
StringBuilder encrpytedValue = new StringBuilder();
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
var encrpytedBlock = FormsAuthentication.Encrypt(new FormsAuthenticationTicket(0, string.Empty, DateTime.Now, DateTime.MaxValue, false, part));
|
||||
encrpytedValue.AppendLine(encrpytedBlock);
|
||||
}
|
||||
|
||||
return encrpytedValue.ToString().TrimEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypt the encrypted string using the Machine key in medium trust
|
||||
/// </summary>
|
||||
/// <param name="value">The string value to be decrypted</param>
|
||||
/// <returns></returns>
|
||||
public static string DecryptWithMachineKey(this string value)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
string[] parts = value.Split('\n');
|
||||
|
||||
StringBuilder decryptedValue = new StringBuilder();
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
decryptedValue.Append(FormsAuthentication.Decrypt(part.TrimEnd()).UserData);
|
||||
}
|
||||
|
||||
return decryptedValue.ToString();
|
||||
}
|
||||
|
||||
//this is from SqlMetal and just makes it a bit of fun to allow pluralisation
|
||||
public static string MakePluralName(this string name)
|
||||
{
|
||||
@@ -119,6 +179,8 @@ namespace Umbraco.Core
|
||||
public static string TrimEnd(this string value, string forRemoving)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) return value;
|
||||
if (string.IsNullOrEmpty(forRemoving)) return value;
|
||||
|
||||
while (value.EndsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
value = value.Remove(value.LastIndexOf(forRemoving, StringComparison.InvariantCultureIgnoreCase));
|
||||
@@ -129,6 +191,8 @@ namespace Umbraco.Core
|
||||
public static string TrimStart(this string value, string forRemoving)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) return value;
|
||||
if (string.IsNullOrEmpty(forRemoving)) return value;
|
||||
|
||||
while (value.StartsWith(forRemoving, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
value = value.Substring(forRemoving.Length);
|
||||
@@ -144,22 +208,22 @@ namespace Umbraco.Core
|
||||
|
||||
public static string EnsureStartsWith(this string input, char value)
|
||||
{
|
||||
return input.StartsWith(value.ToString()) ? input : value + input;
|
||||
return input.StartsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : value + input;
|
||||
}
|
||||
|
||||
public static string EnsureEndsWith(this string input, char value)
|
||||
{
|
||||
return input.EndsWith(value.ToString()) ? input : input + value;
|
||||
return input.EndsWith(value.ToString(CultureInfo.InvariantCulture)) ? input : input + value;
|
||||
}
|
||||
|
||||
public static bool IsLowerCase(this char ch)
|
||||
{
|
||||
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToLower();
|
||||
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
|
||||
}
|
||||
|
||||
public static bool IsUpperCase(this char ch)
|
||||
{
|
||||
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToUpper();
|
||||
return ch.ToString(CultureInfo.InvariantCulture) == ch.ToString(CultureInfo.InvariantCulture).ToUpperInvariant();
|
||||
}
|
||||
|
||||
/// <summary>Is null or white space.</summary>
|
||||
@@ -267,7 +331,7 @@ namespace Umbraco.Core
|
||||
Enumerable.Range(97, 26));
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (var c in value.Where(c => charReplacements.Values.Contains(c.ToString()) || validCodeRanges.Contains(c)))
|
||||
foreach (var c in value.Where(c => charReplacements.Values.Contains(c.ToString(CultureInfo.InvariantCulture)) || validCodeRanges.Contains(c)))
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
@@ -328,7 +392,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (splittedPhraseChars.Length > 0)
|
||||
{
|
||||
splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpper().ToCharArray())[0];
|
||||
splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpperInvariant().ToCharArray())[0];
|
||||
}
|
||||
sb.Append(new String(splittedPhraseChars));
|
||||
}
|
||||
@@ -343,15 +407,15 @@ namespace Umbraco.Core
|
||||
var match = pattern.Match(result);
|
||||
if (match.Success)
|
||||
{
|
||||
result = match.Groups[1].Value.ToLower() + match.Groups[2].Value;
|
||||
result = match.Groups[1].Value.ToLowerInvariant() + match.Groups[2].Value;
|
||||
|
||||
return result.Substring(0, 1).ToLower() + result.Substring(1);
|
||||
return result.Substring(0, 1).ToLowerInvariant() + result.Substring(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result.ToLower();
|
||||
return result.ToLowerInvariant();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
<AssemblyName>Umbraco.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -54,7 +56,7 @@
|
||||
<Compile Include="AssemblyExtensions.cs" />
|
||||
<Compile Include="Attempt.cs" />
|
||||
<Compile Include="CacheHelper.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoDeprecateAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoWillObsoleteAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoExperimentalFeatureAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoProposedPublicAttribute.cs" />
|
||||
<Compile Include="Configuration\FileSystemProviderElement.cs" />
|
||||
@@ -65,8 +67,14 @@
|
||||
<Compile Include="DictionaryExtensions.cs" />
|
||||
<Compile Include="Dictionary\CultureDictionaryFactoryResolver.cs" />
|
||||
<Compile Include="Dictionary\ICultureDictionaryFactory.cs" />
|
||||
<Compile Include="Dynamics\DynamicInstanceHelper.cs" />
|
||||
<Compile Include="Enum.cs" />
|
||||
<Compile Include="Events\MacroErrorEventArgs.cs" />
|
||||
<Compile Include="HashCodeCombiner.cs" />
|
||||
<Compile Include="IO\FileSystemWrapper.cs" />
|
||||
<Compile Include="MacroErrorBehaviour.cs" />
|
||||
<Compile Include="Media\IImageUrlProvider.cs" />
|
||||
<Compile Include="ObjectResolution\LazyManyObjectsResolverbase.cs" />
|
||||
<Compile Include="PublishedContentExtensions.cs" />
|
||||
<Compile Include="Dictionary\ICultureDictionary.cs" />
|
||||
<Compile Include="Dynamics\ClassFactory.cs" />
|
||||
@@ -124,6 +132,7 @@
|
||||
<Compile Include="ObjectResolution\Resolution.cs" />
|
||||
<Compile Include="ObjectResolution\ResolverBase.cs" />
|
||||
<Compile Include="ObjectResolution\SingleObjectResolverBase.cs" />
|
||||
<Compile Include="PublishedContentHelper.cs" />
|
||||
<Compile Include="RenderingEngine.cs" />
|
||||
<Compile Include="TypeExtensions.cs" />
|
||||
<Compile Include="ReadLock.cs" />
|
||||
@@ -157,6 +166,11 @@
|
||||
<Compile Include="WriteLock.cs" />
|
||||
<Compile Include="XmlExtensions.cs" />
|
||||
<Compile Include="XmlHelper.cs" />
|
||||
<Compile Include="Xml\DynamicContext.cs" />
|
||||
<Compile Include="Xml\XmlNamespaces.cs" />
|
||||
<Compile Include="Xml\XmlNodeListFactory.cs" />
|
||||
<Compile Include="Xml\XmlNodeExtensions.cs" />
|
||||
<Compile Include="Xml\XPathVariable.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@@ -169,6 +183,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.Xsl;
|
||||
using System.Xml.XPath;
|
||||
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the evaluation context for fast execution and custom
|
||||
/// variables resolution.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is responsible for resolving variables during dynamic expression execution.
|
||||
/// <para>Discussed in http://weblogs.asp.net/cazzu/archive/2003/10/07/30888.aspx</para>
|
||||
/// <para>Author: Daniel Cazzulino, <a href="http://clariusconsulting.net/kzu">blog</a></para>
|
||||
/// </remarks>
|
||||
public class DynamicContext : XsltContext
|
||||
{
|
||||
#region Private vars
|
||||
|
||||
readonly IDictionary<string, IXsltContextVariable> _variables =
|
||||
new Dictionary<string, IXsltContextVariable>();
|
||||
|
||||
#endregion Private
|
||||
|
||||
#region Constructors & Initialization
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicContext"/> class.
|
||||
/// </summary>
|
||||
public DynamicContext()
|
||||
: base(new NameTable())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicContext"/>
|
||||
/// class with the specified <see cref="NameTable"/>.
|
||||
/// </summary>
|
||||
/// <param name="table">The NameTable to use.</param>
|
||||
public DynamicContext(NameTable table)
|
||||
: base(table)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="context">A previously filled context with the namespaces to use.</param>
|
||||
public DynamicContext(XmlNamespaceManager context)
|
||||
: this(context, new NameTable())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="context">A previously filled context with the namespaces to use.</param>
|
||||
/// <param name="table">The NameTable to use.</param>
|
||||
public DynamicContext(XmlNamespaceManager context, NameTable table)
|
||||
: base(table)
|
||||
{
|
||||
object xml = table.Add(XmlNamespaces.Xml);
|
||||
object xmlns = table.Add(XmlNamespaces.XmlNs);
|
||||
|
||||
if (context == null) return;
|
||||
|
||||
foreach (string prefix in context)
|
||||
{
|
||||
var uri = context.LookupNamespace(prefix);
|
||||
// Use fast object reference comparison to omit forbidden namespace declarations.
|
||||
if (Equals(uri, xml) || Equals(uri, xmlns))
|
||||
continue;
|
||||
if (uri == null)
|
||||
continue;
|
||||
base.AddNamespace(prefix, uri);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Constructors & Initialization
|
||||
|
||||
#region Common Overrides
|
||||
|
||||
/// <summary>
|
||||
/// Implementation equal to <see cref="XsltContext"/>.
|
||||
/// </summary>
|
||||
public override int CompareDocument(string baseUri, string nextbaseUri)
|
||||
{
|
||||
return String.Compare(baseUri, nextbaseUri, false, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same as <see cref="XmlNamespaceManager"/>.
|
||||
/// </summary>
|
||||
public override string LookupNamespace(string prefix)
|
||||
{
|
||||
var key = NameTable.Get(prefix);
|
||||
return key == null ? null : base.LookupNamespace(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same as <see cref="XmlNamespaceManager"/>.
|
||||
/// </summary>
|
||||
public override string LookupPrefix(string uri)
|
||||
{
|
||||
var key = NameTable.Get(uri);
|
||||
return key == null ? null : base.LookupPrefix(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same as <see cref="XsltContext"/>.
|
||||
/// </summary>
|
||||
public override bool PreserveWhitespace(XPathNavigator node)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same as <see cref="XsltContext"/>.
|
||||
/// </summary>
|
||||
public override bool Whitespace
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion Common Overrides
|
||||
|
||||
#region Public Members
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut method that compiles an expression using an empty navigator.
|
||||
/// </summary>
|
||||
/// <param name="xpath">The expression to compile</param>
|
||||
/// <returns>A compiled <see cref="XPathExpression"/>.</returns>
|
||||
public static XPathExpression Compile(string xpath)
|
||||
{
|
||||
return new XmlDocument().CreateNavigator().Compile(xpath);
|
||||
}
|
||||
|
||||
#endregion Public Members
|
||||
|
||||
#region Variable Handling Code
|
||||
|
||||
/// <summary>
|
||||
/// Adds the variable to the dynamic evaluation context.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the variable to add to the context.</param>
|
||||
/// <param name="value">The value of the variable to add to the context.</param>
|
||||
/// <remarks>
|
||||
/// Value type conversion for XPath evaluation is as follows:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>CLR Type</term>
|
||||
/// <description>XPath type</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>System.String</term>
|
||||
/// <description>XPathResultType.String</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>System.Double (or types that can be converted to)</term>
|
||||
/// <description>XPathResultType.Number</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>System.Boolean</term>
|
||||
/// <description>XPathResultType.Boolean</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>System.Xml.XPath.XPathNavigator</term>
|
||||
/// <description>XPathResultType.Navigator</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>System.Xml.XPath.XPathNodeIterator</term>
|
||||
/// <description>XPathResultType.NodeSet</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Others</term>
|
||||
/// <description>XPathResultType.Any</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// <note type="note">See the topic "Compile, Select, Evaluate, and Matches with
|
||||
/// XPath and XPathExpressions" in MSDN documentation for additional information.</note>
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="value"/> is null.</exception>
|
||||
public void AddVariable(string name, object value)
|
||||
{
|
||||
if (value == null) throw new ArgumentNullException("value");
|
||||
_variables[name] = new DynamicVariable(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See <see cref="XsltContext"/>. Not used in our implementation.
|
||||
/// </summary>
|
||||
public override IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] argTypes)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the dynamic variables added to the context. See <see cref="XsltContext"/>.
|
||||
/// </summary>
|
||||
public override IXsltContextVariable ResolveVariable(string prefix, string name)
|
||||
{
|
||||
IXsltContextVariable var;
|
||||
_variables.TryGetValue(name, out var);
|
||||
return var;
|
||||
}
|
||||
|
||||
#endregion Variable Handling Code
|
||||
|
||||
#region Internal DynamicVariable class
|
||||
|
||||
/// <summary>
|
||||
/// Represents a variable during dynamic expression execution.
|
||||
/// </summary>
|
||||
internal class DynamicVariable : IXsltContextVariable
|
||||
{
|
||||
readonly string _name;
|
||||
readonly object _value;
|
||||
|
||||
#region Public Members
|
||||
|
||||
public string Name { get { return _name; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the variable.</param>
|
||||
/// <param name="value">The value of the variable.</param>
|
||||
public DynamicVariable(string name, object value)
|
||||
{
|
||||
|
||||
_name = name;
|
||||
_value = value;
|
||||
|
||||
if (value is String)
|
||||
_type = XPathResultType.String;
|
||||
else if (value is bool)
|
||||
_type = XPathResultType.Boolean;
|
||||
else if (value is XPathNavigator)
|
||||
_type = XPathResultType.Navigator;
|
||||
else if (value is XPathNodeIterator)
|
||||
_type = XPathResultType.NodeSet;
|
||||
else
|
||||
{
|
||||
// Try to convert to double (native XPath numeric type)
|
||||
if (value is double)
|
||||
{
|
||||
_type = XPathResultType.Number;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value is IConvertible)
|
||||
{
|
||||
try
|
||||
{
|
||||
_value = Convert.ToDouble(value);
|
||||
// We suceeded, so it's a number.
|
||||
_type = XPathResultType.Number;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
_type = XPathResultType.Any;
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
_type = XPathResultType.Any;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_type = XPathResultType.Any;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Members
|
||||
|
||||
#region IXsltContextVariable Implementation
|
||||
|
||||
XPathResultType IXsltContextVariable.VariableType
|
||||
{
|
||||
get { return _type; }
|
||||
}
|
||||
|
||||
readonly XPathResultType _type;
|
||||
|
||||
object IXsltContextVariable.Evaluate(XsltContext context)
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
bool IXsltContextVariable.IsLocal
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
bool IXsltContextVariable.IsParam
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
#endregion IXsltContextVariable Implementation
|
||||
}
|
||||
|
||||
#endregion Internal DynamicVariable class
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
internal class XPathVariable
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public XPathVariable(string name, string value)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides public constants for wellknown XML namespaces.
|
||||
/// </summary>
|
||||
/// <remarks>Author: Daniel Cazzulino, <a href="http://clariusconsulting.net/kzu">blog</a></remarks>
|
||||
public static class XmlNamespaces
|
||||
{
|
||||
/// <summary>
|
||||
/// The public XML 1.0 namespace.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.w3.org/TR/2004/REC-xml-20040204/</remarks>
|
||||
public const string Xml = "http://www.w3.org/XML/1998/namespace";
|
||||
|
||||
/// <summary>
|
||||
/// Public Xml Namespaces specification namespace.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.w3.org/TR/REC-xml-names/</remarks>
|
||||
public const string XmlNs = "http://www.w3.org/2000/xmlns/";
|
||||
|
||||
/// <summary>
|
||||
/// Public Xml Namespaces prefix.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.w3.org/TR/REC-xml-names/</remarks>
|
||||
public const string XmlNsPrefix = "xmlns";
|
||||
|
||||
/// <summary>
|
||||
/// XML Schema instance namespace.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.w3.org/TR/xmlschema-1/</remarks>
|
||||
public const string Xsi = "http://www.w3.org/2001/XMLSchema-instance";
|
||||
|
||||
/// <summary>
|
||||
/// XML 1.0 Schema namespace.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.w3.org/TR/xmlschema-1/</remarks>
|
||||
public const string Xsd = "http://www.w3.org/2001/XMLSchema";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
internal static class XmlNodeExtensions
|
||||
{
|
||||
static XPathNodeIterator Select(string expression, XPathNavigator source, params XPathVariable[] variables)
|
||||
{
|
||||
var expr = source.Compile(expression);
|
||||
var context = new DynamicContext();
|
||||
foreach (var variable in variables)
|
||||
context.AddVariable(variable.Name, variable.Value);
|
||||
expr.SetContext(context);
|
||||
return source.Select(expr);
|
||||
}
|
||||
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
}
|
||||
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = Select(expression, source.CreateNavigator(), variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
}
|
||||
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
// source: mvpxml.codeplex.com
|
||||
|
||||
namespace Umbraco.Core.Xml
|
||||
{
|
||||
class XmlNodeListFactory
|
||||
{
|
||||
private XmlNodeListFactory() { }
|
||||
|
||||
#region Public members
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a <see cref="XmlNodeList"/> that allows
|
||||
/// enumerating <see cref="XmlNode"/> elements in the iterator.
|
||||
/// </summary>
|
||||
/// <param name="iterator">The result of a previous node selection
|
||||
/// through an <see cref="XPathNavigator"/> query.</param>
|
||||
/// <returns>An initialized list ready to be enumerated.</returns>
|
||||
/// <remarks>The underlying XML store used to issue the query must be
|
||||
/// an object inheriting <see cref="XmlNode"/>, such as
|
||||
/// <see cref="XmlDocument"/>.</remarks>
|
||||
public static XmlNodeList CreateNodeList(XPathNodeIterator iterator)
|
||||
{
|
||||
return new XmlNodeListIterator(iterator);
|
||||
}
|
||||
|
||||
#endregion Public members
|
||||
|
||||
#region XmlNodeListIterator
|
||||
|
||||
private class XmlNodeListIterator : XmlNodeList
|
||||
{
|
||||
readonly XPathNodeIterator _iterator;
|
||||
readonly IList<XmlNode> _nodes = new List<XmlNode>();
|
||||
|
||||
public XmlNodeListIterator(XPathNodeIterator iterator)
|
||||
{
|
||||
_iterator = iterator.Clone();
|
||||
}
|
||||
|
||||
public override System.Collections.IEnumerator GetEnumerator()
|
||||
{
|
||||
return new XmlNodeListEnumerator(this);
|
||||
}
|
||||
|
||||
public override XmlNode Item(int index)
|
||||
{
|
||||
|
||||
if (index >= _nodes.Count)
|
||||
ReadTo(index);
|
||||
// Compatible behavior with .NET
|
||||
if (index >= _nodes.Count || index < 0)
|
||||
return null;
|
||||
return _nodes[index];
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_done) ReadToEnd();
|
||||
return _nodes.Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads the entire iterator.
|
||||
/// </summary>
|
||||
private void ReadToEnd()
|
||||
{
|
||||
while (_iterator.MoveNext())
|
||||
{
|
||||
var node = _iterator.Current as IHasXmlNode;
|
||||
// Check IHasXmlNode interface.
|
||||
if (node == null)
|
||||
throw new ArgumentException("IHasXmlNode is missing.");
|
||||
_nodes.Add(node.GetNode());
|
||||
}
|
||||
_done = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to the specified index, or until the
|
||||
/// iterator is consumed.
|
||||
/// </summary>
|
||||
private void ReadTo(int to)
|
||||
{
|
||||
while (_nodes.Count <= to)
|
||||
{
|
||||
if (_iterator.MoveNext())
|
||||
{
|
||||
var node = _iterator.Current as IHasXmlNode;
|
||||
// Check IHasXmlNode interface.
|
||||
if (node == null)
|
||||
throw new ArgumentException("IHasXmlNode is missing.");
|
||||
_nodes.Add(node.GetNode());
|
||||
}
|
||||
else
|
||||
{
|
||||
_done = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flags that the iterator has been consumed.
|
||||
/// </summary>
|
||||
private bool Done
|
||||
{
|
||||
get { return _done; }
|
||||
}
|
||||
|
||||
bool _done;
|
||||
|
||||
/// <summary>
|
||||
/// Current count of nodes in the iterator (read so far).
|
||||
/// </summary>
|
||||
private int CurrentPosition
|
||||
{
|
||||
get { return _nodes.Count; }
|
||||
}
|
||||
|
||||
#region XmlNodeListEnumerator
|
||||
|
||||
private class XmlNodeListEnumerator : System.Collections.IEnumerator
|
||||
{
|
||||
readonly XmlNodeListIterator _iterator;
|
||||
int _position = -1;
|
||||
|
||||
public XmlNodeListEnumerator(XmlNodeListIterator iterator)
|
||||
{
|
||||
_iterator = iterator;
|
||||
}
|
||||
|
||||
#region IEnumerator Members
|
||||
|
||||
void System.Collections.IEnumerator.Reset()
|
||||
{
|
||||
_position = -1;
|
||||
}
|
||||
|
||||
|
||||
bool System.Collections.IEnumerator.MoveNext()
|
||||
{
|
||||
_position++;
|
||||
_iterator.ReadTo(_position);
|
||||
|
||||
// If we reached the end and our index is still
|
||||
// bigger, there're no more items.
|
||||
if (_iterator.Done && _position >= _iterator.CurrentPosition)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
object System.Collections.IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return _iterator[_position];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion XmlNodeListEnumerator
|
||||
}
|
||||
|
||||
#endregion XmlNodeListIterator
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
CreateNew();
|
||||
}
|
||||
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Get_Top_Level_Items()
|
||||
{
|
||||
@@ -42,6 +43,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// Creates a new dictionary entry, adds values for all languages assigned, then deletes the
|
||||
/// entry and ensure that all other data is gone too.
|
||||
///</summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Create_Add_Text_And_Delete()
|
||||
{
|
||||
@@ -64,6 +66,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
///A test for IsTopMostItem
|
||||
///</summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_IsTopMostItem()
|
||||
{
|
||||
@@ -85,6 +88,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
/// Test the Parent and Children properties and ensures that the relationships work both ways
|
||||
///</summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Parent_Child_Relationship()
|
||||
{
|
||||
@@ -115,6 +119,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
/// Deletes a parent with existing children and ensures they are all gone.
|
||||
/// </summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Delete_Parent_With_Children()
|
||||
{
|
||||
@@ -166,6 +171,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
/// Guid constructor test
|
||||
///</summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Contructor_Guid()
|
||||
{
|
||||
@@ -183,6 +189,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
/// key constructor test
|
||||
/// </summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Contructor_Key()
|
||||
{
|
||||
@@ -200,6 +207,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
///A test for ToXml
|
||||
///</summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_ToXml()
|
||||
{
|
||||
@@ -227,6 +235,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
/// <summary>
|
||||
///A test to change the key of an element
|
||||
///</summary>
|
||||
[Ignore]
|
||||
[Test()]
|
||||
public void Dictionary_Change_Key()
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Umbraco.Tests
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Tests
|
||||
};
|
||||
|
||||
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
|
||||
PluginManager.Current.ResolveCacheRefreshers());
|
||||
() => PluginManager.Current.ResolveCacheRefreshers());
|
||||
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Linq;
|
||||
using System.Xml;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Routing;
|
||||
@@ -54,6 +55,8 @@ namespace Umbraco.Tests.ContentStores
|
||||
</Home>
|
||||
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1045"" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
|
||||
</Home>
|
||||
<Home id=""1177"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1045"" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub'Apostrophe"" urlName=""sub'apostrophe"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1177"" isDoc=""""><content><![CDATA[]]></content>
|
||||
</Home>
|
||||
</Home>
|
||||
<Home id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""1045"" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
|
||||
</root>";
|
||||
@@ -63,7 +66,7 @@ namespace Umbraco.Tests.ContentStores
|
||||
public void SetUp()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
Umbraco.Core.Configuration.UmbracoSettings.UseLegacyXmlSchema = false;
|
||||
|
||||
_httpContextFactory = new FakeHttpContextFactory("~/Home");
|
||||
//ensure the StateHelper is using our custom context
|
||||
StateHelper.HttpContext = _httpContextFactory.HttpContext;
|
||||
@@ -103,9 +106,7 @@ namespace Umbraco.Tests.ContentStores
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
//TODO: need to reset everything!
|
||||
|
||||
Umbraco.Core.Configuration.UmbracoSettings.UseLegacyXmlSchema = false;
|
||||
UmbracoSettings.ResetSetters();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -155,6 +156,7 @@ namespace Umbraco.Tests.ContentStores
|
||||
[TestCase("/home/sub1", 1173)]
|
||||
[TestCase("/Home/sub1", 1173)]
|
||||
[TestCase("/home/Sub1", 1173)] //test different cases
|
||||
[TestCase("/home/Sub'Apostrophe", 1177)]
|
||||
public void Get_Node_By_Route(string route, int nodeId)
|
||||
{
|
||||
var result = _publishedContentStore.GetDocumentByRoute(_umbracoContext, route, false);
|
||||
|
||||
@@ -1,18 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Examine;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.PublishedContent;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using umbraco.BusinessLogic;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
namespace Umbraco.Tests.ContentStores
|
||||
{
|
||||
[TestFixture]
|
||||
public class PublishMediaStoreTests
|
||||
public class PublishMediaStoreTests : PublishedContentTestBase
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Root_Docs()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot1", mType, user, -1);
|
||||
var mRoot2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot2", mType, user, -1);
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot1.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot2.Id);
|
||||
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var mediaStore = new DefaultPublishedMediaStore();
|
||||
var roots = mediaStore.GetRootDocuments(ctx);
|
||||
Assert.AreEqual(2, roots.Count());
|
||||
Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id}));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Item_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var publishedMedia = PublishedMediaTests.GetNode(mRoot.Id, GetUmbracoContext("/test", 1234));
|
||||
|
||||
Assert.AreEqual(mRoot.Id, publishedMedia.Id);
|
||||
Assert.AreEqual(mRoot.CreateDateTime.ToString("dd/MM/yyyy HH:mm:ss"), publishedMedia.CreateDate.ToString("dd/MM/yyyy HH:mm:ss"));
|
||||
Assert.AreEqual(mRoot.User.Id, publishedMedia.CreatorId);
|
||||
Assert.AreEqual(mRoot.User.Name, publishedMedia.CreatorName);
|
||||
Assert.AreEqual(mRoot.ContentType.Alias, publishedMedia.DocumentTypeAlias);
|
||||
Assert.AreEqual(mRoot.ContentType.Id, publishedMedia.DocumentTypeId);
|
||||
Assert.AreEqual(mRoot.Level, publishedMedia.Level);
|
||||
Assert.AreEqual(mRoot.Text, publishedMedia.Name);
|
||||
Assert.AreEqual(mRoot.Path, publishedMedia.Path);
|
||||
Assert.AreEqual(mRoot.sortOrder, publishedMedia.SortOrder);
|
||||
Assert.IsNull(publishedMedia.Parent);
|
||||
}
|
||||
|
||||
[TestCase("id")]
|
||||
[TestCase("nodeId")]
|
||||
[TestCase("__NodeId")]
|
||||
@@ -191,10 +255,12 @@ namespace Umbraco.Tests
|
||||
a => null,
|
||||
//we're not going to test this so ignore
|
||||
a => new List<IPublishedContent>(),
|
||||
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a))),
|
||||
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a)),
|
||||
false),
|
||||
//callback to get the children
|
||||
d => children,
|
||||
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a)));
|
||||
(dd, a) => dd.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(a)),
|
||||
false);
|
||||
return dicDoc;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Tests
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Tests
|
||||
};
|
||||
|
||||
DataTypesResolver.Current = new DataTypesResolver(
|
||||
PluginManager.Current.ResolveDataTypes());
|
||||
() => PluginManager.Current.ResolveDataTypes());
|
||||
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
@@ -1,639 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
{
|
||||
[TestFixture]
|
||||
public abstract class DynamicDocumentTestsBase<TDocument, TDocumentList> : BaseRoutingTest
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
}
|
||||
|
||||
protected override bool RequiresDbSetup
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
protected override string GetXmlContent(int templateId)
|
||||
{
|
||||
return @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<!DOCTYPE root[
|
||||
<!ELEMENT Home ANY>
|
||||
<!ATTLIST Home id ID #REQUIRED>
|
||||
<!ELEMENT CustomDocument ANY>
|
||||
<!ATTLIST CustomDocument id ID #REQUIRED>
|
||||
]>
|
||||
<root id=""-1"">
|
||||
<Home id=""1046"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Home"" urlName=""home"" writerName=""admin"" creatorName=""admin"" path=""-1,1046"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
|
||||
<content><![CDATA[<div>This is some content</div>]]></content>
|
||||
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
|
||||
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
|
||||
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
|
||||
</Home>
|
||||
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
|
||||
<content><![CDATA[some content]]></content>
|
||||
<blah><![CDATA[some content]]></blah>
|
||||
</Home>
|
||||
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
|
||||
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
|
||||
</Home>
|
||||
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
|
||||
</Home>
|
||||
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
|
||||
<selectedNodes><![CDATA[1172,1176,1173]]></selectedNodes>
|
||||
<CustomDocument id=""5555"" parentID=""1046"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""0"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444,5555"" isDoc="""">
|
||||
</CustomDocument>
|
||||
</CustomDocument>
|
||||
</Home>
|
||||
<CustomDocument id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
|
||||
</root>";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dynamic node/document to run tests against
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract dynamic GetDynamicNode(int id);
|
||||
|
||||
[Test]
|
||||
public void Single()
|
||||
{
|
||||
var doc = GetDynamicNode(4444);
|
||||
|
||||
var result = doc.Children().Single();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(5555, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Single_With_Query()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var result = doc.Children().Single("id==1175");
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1175, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void First()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var result = doc.Children().First();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1174, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void First_With_Query()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var result = doc.Children().First("blah==\"some content\"");
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1176, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_User_Property_Value()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var result = (IEnumerable<dynamic>)doc.Children().Where("blah==\"some content\"");
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual(1176, result.Single().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void String_ContainsValue_Extension_Method()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var paramVals = new Dictionary<string, object> { { "searchId", 1173 } }; //this is an integer value
|
||||
var result = doc.Children()
|
||||
.Where("selectedNodes.ContainsValue(searchId)", paramVals) //call an extension method
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
|
||||
//don't find!
|
||||
paramVals = new Dictionary<string, object> { { "searchId", 1111777 } };
|
||||
result = doc.Children()
|
||||
.Where("selectedNodes.ContainsValue(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsTrue(result.GetType() == typeof(DynamicNull) || result.GetType() == typeof(umbraco.MacroEngines.DynamicNull));
|
||||
//Assert.AreEqual(typeof(DynamicNull), result.GetType());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void String_Contains_Method()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var paramVals = new Dictionary<string, object> { { "searchId", "1173" } };
|
||||
var result = doc.Children()
|
||||
.Where("selectedNodes.Contains(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
|
||||
//don't find!
|
||||
paramVals = new Dictionary<string, object> { { "searchId", "1aaa173" } };
|
||||
result = doc.Children()
|
||||
.Where("selectedNodes.Contains(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsTrue(result.GetType() == typeof (DynamicNull) || result.GetType() == typeof (umbraco.MacroEngines.DynamicNull));
|
||||
//Assert.AreEqual(typeof (DynamicNull), result.GetType());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void String_Split_Method()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var paramVals = new Dictionary<string, object>
|
||||
{
|
||||
{ "splitTerm", new char[] { ',' } },
|
||||
{ "splitOptions", StringSplitOptions.RemoveEmptyEntries }
|
||||
};
|
||||
var result = doc.Children()
|
||||
.Where("selectedNodes.Split(splitTerm, splitOptions).Length == 3", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Complex_Linq()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var paramVals = new Dictionary<string, object> {{"splitTerm", new char[] {','}}, {"searchId", "1173"}};
|
||||
var result = doc.Ancestors().OrderBy("level")
|
||||
.Single()
|
||||
.Descendants()
|
||||
.Where("selectedNodes != null && selectedNodes != String.Empty && selectedNodes.Split(splitTerm).Contains(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Index()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
Assert.AreEqual(0, doc.Index());
|
||||
doc = GetDynamicNode(1176);
|
||||
Assert.AreEqual(1, doc.Index());
|
||||
doc = GetDynamicNode(1177);
|
||||
Assert.AreEqual(2, doc.Index());
|
||||
doc = GetDynamicNode(1178);
|
||||
Assert.AreEqual(3, doc.Index());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_First()
|
||||
{
|
||||
var doc = GetDynamicNode(1046); //test root nodes
|
||||
Assert.IsTrue(doc.IsFirst());
|
||||
doc = GetDynamicNode(1172);
|
||||
Assert.IsFalse(doc.IsFirst());
|
||||
doc = GetDynamicNode(1173); //test normal nodes
|
||||
Assert.IsTrue(doc.IsFirst());
|
||||
doc = GetDynamicNode(1175);
|
||||
Assert.IsFalse(doc.IsFirst());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Not_First()
|
||||
{
|
||||
var doc = GetDynamicNode(1046); //test root nodes
|
||||
Assert.IsFalse(doc.IsNotFirst());
|
||||
doc = GetDynamicNode(1172);
|
||||
Assert.IsTrue(doc.IsNotFirst());
|
||||
doc = GetDynamicNode(1173); //test normal nodes
|
||||
Assert.IsFalse(doc.IsNotFirst());
|
||||
doc = GetDynamicNode(1175);
|
||||
Assert.IsTrue(doc.IsNotFirst());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Position()
|
||||
{
|
||||
var doc = GetDynamicNode(1046); //test root nodes
|
||||
Assert.IsTrue(doc.IsPosition(0));
|
||||
doc = GetDynamicNode(1172);
|
||||
Assert.IsTrue(doc.IsPosition(1));
|
||||
doc = GetDynamicNode(1173); //test normal nodes
|
||||
Assert.IsTrue(doc.IsPosition(0));
|
||||
doc = GetDynamicNode(1175);
|
||||
Assert.IsTrue(doc.IsPosition(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_GroupBy_DocumentTypeAlias()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var found1 = doc.Children.GroupBy("DocumentTypeAlias");
|
||||
|
||||
var casted = (IEnumerable<IGrouping<object, dynamic>>)(found1);
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
Assert.AreEqual(2, casted.Single(x => x.Key.ToString() == "Home").Count());
|
||||
Assert.AreEqual(1, casted.Single(x => x.Key.ToString() == "CustomDocument").Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Where_DocumentTypeAlias()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var found1 = doc.Children.Where("DocumentTypeAlias == \"CustomDocument\"");
|
||||
var found2 = doc.Children.Where("DocumentTypeAlias == \"Home\"");
|
||||
|
||||
Assert.AreEqual(1, found1.Count());
|
||||
Assert.AreEqual(2, found2.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Where_NodeTypeAlias()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var found1 = doc.Children.Where("NodeTypeAlias == \"CustomDocument\"");
|
||||
var found2 = doc.Children.Where("NodeTypeAlias == \"Home\"");
|
||||
|
||||
Assert.AreEqual(1, found1.Count());
|
||||
Assert.AreEqual(2, found2.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Order_By_Update_Date()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var ordered = asDynamic.Children.OrderBy("UpdateDate");
|
||||
var casted = (IEnumerable<TDocument>)ordered;
|
||||
|
||||
var correctOrder = new[] { 1178, 1177, 1174, 1176 };
|
||||
for (var i = 0; i < correctOrder.Length ;i++)
|
||||
{
|
||||
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Order_By_Update_Date_Descending()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var ordered = asDynamic.Children.OrderBy("UpdateDate desc");
|
||||
var casted = (IEnumerable<TDocument>)ordered;
|
||||
|
||||
var correctOrder = new[] { 1176, 1174, 1177, 1178 };
|
||||
for (var i = 0; i < correctOrder.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasProperty()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var hasProp = asDynamic.HasProperty("umbracoUrlAlias");
|
||||
|
||||
Assert.AreEqual(true, (bool)hasProp);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Skip()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var skip = asDynamic.Children.Skip(2);
|
||||
var casted = (IEnumerable<TDocument>)skip;
|
||||
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[]{1177, 1178}));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasValue()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var hasValue = asDynamic.HasValue("umbracoUrlAlias");
|
||||
var noValue = asDynamic.HasValue("blahblahblah");
|
||||
|
||||
Assert.IsTrue(hasValue);
|
||||
Assert.IsFalse(noValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Take()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var take = asDynamic.Children.Take(2);
|
||||
var casted = (IEnumerable<TDocument>)take;
|
||||
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1176 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors_Where_Visible()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
var whereVisible = asDynamic.Ancestors().Where("Visible");
|
||||
var casted = (IEnumerable<TDocument>)whereVisible;
|
||||
|
||||
Assert.AreEqual(1, casted.Count());
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Visible()
|
||||
{
|
||||
var asDynamicHidden = GetDynamicNode(1046);
|
||||
var asDynamicVisible = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsFalse(asDynamicHidden.Visible);
|
||||
Assert.IsTrue(asDynamicVisible.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_TinyMCE_Converted_Type_User_Property()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(asDynamic.Content.GetType()));
|
||||
Assert.AreEqual("<div>This is some content</div>", asDynamic.Content.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Children_With_Pluralized_Alias()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Action<object> doAssert = d =>
|
||||
{
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(d));
|
||||
var casted = (IEnumerable<TDocument>)d;
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
};
|
||||
|
||||
doAssert(asDynamic.Homes); //pluralized alias
|
||||
doAssert(asDynamic.homes); //pluralized alias
|
||||
doAssert(asDynamic.CustomDocuments); //pluralized alias
|
||||
doAssert(asDynamic.customDocuments); //pluralized alias
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPropertyValue_Non_Reflected()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("creatorName"));
|
||||
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("CreatorName"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPropertyValue_Reflected()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@creatorName"));
|
||||
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@CreatorName"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_User_Property_With_Same_Name_As_Member_Property()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.creatorName);
|
||||
|
||||
//because CreatorName is defined on DynamicNode, it will not return the user defined property
|
||||
Assert.AreEqual("admin", asDynamic.CreatorName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Member_Property()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Assert.AreEqual((int) 2, (int) asDynamic.Level);
|
||||
Assert.AreEqual((int) 2, (int) asDynamic.level);
|
||||
|
||||
Assert.AreEqual((int) 1046, (int) asDynamic.ParentId);
|
||||
Assert.AreEqual((int) 1046, (int) asDynamic.parentId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Children()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var children = asDynamic.Children;
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(children));
|
||||
|
||||
var childrenAsList = asDynamic.ChildrenAsList; //test ChildrenAsList too
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(childrenAsList));
|
||||
|
||||
var castChildren = (IEnumerable<TDocument>)children;
|
||||
Assert.AreEqual(4, castChildren.Count());
|
||||
|
||||
var castChildrenAsList = (IEnumerable<TDocument>)childrenAsList;
|
||||
Assert.AreEqual(4, castChildrenAsList.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestor_Or_Self()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.AncestorOrSelf();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int) 1046, (int) result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors_Or_Self()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
var result = asDynamic.AncestorsOrSelf();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(3, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
var result = asDynamic.Ancestors();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(2, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants_Or_Self()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1046);
|
||||
|
||||
var result = asDynamic.DescendantsOrSelf();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(9, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175, 4444 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1046);
|
||||
|
||||
var result = asDynamic.Descendants();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(8, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Up()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.Up();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int) 1046, (int) result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Down()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.Down();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int) 1174, (int) result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Next()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.Next();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int) 1175, (int) result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Next_Without_Sibling()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1178);
|
||||
|
||||
Assert.IsNull(asDynamic.Next());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Previous_Without_Sibling()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsNull(asDynamic.Previous());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Previous()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1176);
|
||||
|
||||
var result = asDynamic.Previous();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int) 1174, (int) result.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods used in tests
|
||||
/// </summary>
|
||||
public static class TestExtensionMethods
|
||||
{
|
||||
public static bool ContainsValue(this string s, int val)
|
||||
{
|
||||
return s.Contains(val.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.IO;
|
||||
using umbraco.MacroEngines;
|
||||
using umbraco.NodeFactory;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.cms.businesslogic.template;
|
||||
using System.Linq;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
{
|
||||
[TestFixture]
|
||||
public class DynamicNodeTests : DynamicDocumentTestsBase<DynamicNode, DynamicNodeList>
|
||||
{
|
||||
protected override bool RequiresDbSetup
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
//copy the umbraco settings file over
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
UmbracoSettings.SettingsFilePath = IOHelper.MapPath(SystemDirectories.Config, false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
{
|
||||
typeof(DynamicNode).Assembly
|
||||
};
|
||||
|
||||
//need to specify a custom callback for unit tests
|
||||
DynamicNode.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
|
||||
{
|
||||
if (propertyAlias == "content")
|
||||
{
|
||||
//return the rte type id
|
||||
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
|
||||
}
|
||||
return Guid.Empty;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
PluginManager.Current.AssembliesToScan = null;
|
||||
}
|
||||
|
||||
protected override dynamic GetDynamicNode(int id)
|
||||
{
|
||||
//var template = Template.MakeNew("test", new User(0));
|
||||
//var ctx = GetUmbracoContext("/test", template.Id);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var contentStore = new DefaultPublishedContentStore();
|
||||
var node = new DynamicNode(
|
||||
new DynamicBackingItem(
|
||||
new Node(ctx.GetXml().SelectSingleNode("//*[@id='" + id + "' and @isDoc]"))));
|
||||
Assert.IsNotNull(node);
|
||||
return (dynamic) node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.CSharp.RuntimeBinder;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Dynamics;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
{
|
||||
[TestFixture]
|
||||
public class DynamicXmlTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Ensure_Legacy_Objects_Are_Returned()
|
||||
{
|
||||
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
|
||||
var mediaItems = new global::umbraco.MacroEngines.DynamicXml(xml);
|
||||
//Debug.WriteLine("full xml = {0}", mediaItems.ToXml());
|
||||
|
||||
if (mediaItems.Count() != 0)
|
||||
{
|
||||
foreach (dynamic item in mediaItems)
|
||||
{
|
||||
Type itemType = item.GetType();
|
||||
Debug.WriteLine("item type = {0}", itemType);
|
||||
dynamic image = item.Image;
|
||||
|
||||
Type imageType = image.GetType();
|
||||
Debug.WriteLine("image type = {0}", imageType);
|
||||
|
||||
//ensure they are the same
|
||||
Assert.AreEqual(itemType, imageType);
|
||||
|
||||
//ensure they are legacy
|
||||
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), itemType);
|
||||
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), imageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the current Core class
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Find_Test_Core_Class()
|
||||
{
|
||||
RunFindTest(x => new DynamicXml(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the macroEngines legacy class
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Find_Test_Legacy_Class()
|
||||
{
|
||||
RunFindTest(x => new global::umbraco.MacroEngines.DynamicXml(x));
|
||||
}
|
||||
|
||||
private void RunFindTest(Func<string, dynamic> getDynamicXml)
|
||||
{
|
||||
var xmlstring = @"<test>
|
||||
<item id='1' name='test 1' value='found 1'/>
|
||||
<item id='2' name='test 2' value='found 2'/>
|
||||
<item id='3' name='test 3' value='found 3'/>
|
||||
</test>";
|
||||
|
||||
dynamic dXml = getDynamicXml(xmlstring);
|
||||
|
||||
var result1 = dXml.Find("@name", "test 1");
|
||||
var result2 = dXml.Find("@name", "test 2");
|
||||
var result3 = dXml.Find("@name", "test 3");
|
||||
var result4 = dXml.Find("@name", "dont find");
|
||||
|
||||
Assert.AreEqual("found 1", result1.value);
|
||||
Assert.AreEqual("found 2", result2.value);
|
||||
Assert.AreEqual("found 3", result3.value);
|
||||
Assert.Throws<RuntimeBinderException>(() =>
|
||||
{
|
||||
//this will throw because result4 is not found
|
||||
var temp = result4.value;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,77 @@ namespace Umbraco.Tests
|
||||
[TestFixture]
|
||||
public class EnumerableExtensionsTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Flatten_List()
|
||||
{
|
||||
var hierarchy = new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem(),
|
||||
new TestItem()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
}
|
||||
}
|
||||
},
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
{
|
||||
new TestItem()
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
var flattened = hierarchy.Children.FlattenList(x => x.Children);
|
||||
|
||||
Assert.AreEqual(10, flattened.Count());
|
||||
}
|
||||
|
||||
private class TestItem
|
||||
{
|
||||
public TestItem()
|
||||
{
|
||||
Children = Enumerable.Empty<TestItem>();
|
||||
}
|
||||
public IEnumerable<TestItem> Children { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InGroupsOf_ReturnsAllElements()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Configuration;
|
||||
using System.Web.Routing;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
@@ -13,21 +16,34 @@ namespace Umbraco.Tests
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
{
|
||||
base.Initialize();
|
||||
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "~/umbraco,~/install/");
|
||||
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd");
|
||||
SettingsForTests.UmbracoPath = "~/umbraco";
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
//ensure this is reset
|
||||
SystemDirectories.Root = null;
|
||||
SettingsForTests.UmbracoPath = "~/umbraco";
|
||||
//reset the app config
|
||||
base.TearDown();
|
||||
//reset the app config
|
||||
ConfigurationManager.AppSettings.Set("umbracoReservedPaths", "");
|
||||
ConfigurationManager.AppSettings.Set("umbracoReservedUrls", "");
|
||||
|
||||
}
|
||||
|
||||
[TestCase("/umbraco/umbraco.aspx")]
|
||||
[TestCase("~/umbraco", "/", "umbraco")]
|
||||
[TestCase("~/umbraco", "/MyVirtualDir", "umbraco")]
|
||||
[TestCase("~/customPath", "/MyVirtualDir/", "custompath")]
|
||||
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir", "some-wacky-nestedpath")]
|
||||
[TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")]
|
||||
public void Umbraco_Mvc_Area(string path, string rootPath, string outcome)
|
||||
{
|
||||
SettingsForTests.UmbracoPath = path;
|
||||
SystemDirectories.Root = rootPath;
|
||||
Assert.AreEqual(outcome, Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea);
|
||||
}
|
||||
|
||||
[TestCase("/umbraco/umbraco.aspx")]
|
||||
[TestCase("/umbraco/editContent.aspx")]
|
||||
[TestCase("/install/default.aspx")]
|
||||
[TestCase("/install/")]
|
||||
@@ -53,5 +69,42 @@ namespace Umbraco.Tests
|
||||
{
|
||||
Assert.IsFalse(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
|
||||
}
|
||||
|
||||
|
||||
[TestCase("/Do/Not/match", false)]
|
||||
[TestCase("/Umbraco/RenderMvcs", false)]
|
||||
[TestCase("/Umbraco/RenderMvc", true)]
|
||||
[TestCase("/Umbraco/RenderMvc/Index", true)]
|
||||
[TestCase("/Umbraco/RenderMvc/Index/1234", true)]
|
||||
[TestCase("/Umbraco/RenderMvc/Index/1234/9876", false)]
|
||||
[TestCase("/api", true)]
|
||||
[TestCase("/api/WebApiTest", true)]
|
||||
[TestCase("/api/WebApiTest/1234", true)]
|
||||
[TestCase("/api/WebApiTest/Index/1234", false)]
|
||||
public void Is_Reserved_By_Route(string url, bool shouldMatch)
|
||||
{
|
||||
//reset the app config, we only want to test routes not the hard coded paths
|
||||
Umbraco.Core.Configuration.GlobalSettings.ReservedPaths = "";
|
||||
Umbraco.Core.Configuration.GlobalSettings.ReservedUrls = "";
|
||||
|
||||
var routes = new RouteCollection();
|
||||
|
||||
routes.MapRoute(
|
||||
"Umbraco_default",
|
||||
"Umbraco/RenderMvc/{action}/{id}",
|
||||
new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional });
|
||||
routes.MapRoute(
|
||||
"WebAPI",
|
||||
"api/{controller}/{id}",
|
||||
new { controller = "WebApiTestController", action = "Index", id = UrlParameter.Optional });
|
||||
|
||||
|
||||
var context = new FakeHttpContextFactory(url);
|
||||
|
||||
|
||||
Assert.AreEqual(
|
||||
shouldMatch,
|
||||
Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url, context.HttpContext, routes));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class HashCodeCombinerTests : PartialTrust.AbstractPartialTrustFixture<HashCodeCombinerTests>
|
||||
{
|
||||
|
||||
private DirectoryInfo PrepareFolder()
|
||||
{
|
||||
var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
|
||||
var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "HashCombiner", Guid.NewGuid().ToString("N")));
|
||||
foreach (var f in dir.GetFiles())
|
||||
{
|
||||
f.Delete();
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HashCombiner_Test_String()
|
||||
{
|
||||
var combiner1 = new HashCodeCombiner();
|
||||
combiner1.AddCaseInsensitiveString("Hello");
|
||||
|
||||
var combiner2 = new HashCodeCombiner();
|
||||
combiner2.AddCaseInsensitiveString("hello");
|
||||
|
||||
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
|
||||
combiner2.AddCaseInsensitiveString("world");
|
||||
|
||||
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HashCombiner_Test_Int()
|
||||
{
|
||||
var combiner1 = new HashCodeCombiner();
|
||||
combiner1.AddInt(1234);
|
||||
|
||||
var combiner2 = new HashCodeCombiner();
|
||||
combiner2.AddInt(1234);
|
||||
|
||||
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
|
||||
combiner2.AddInt(1);
|
||||
|
||||
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HashCombiner_Test_DateTime()
|
||||
{
|
||||
var dt = DateTime.Now;
|
||||
var combiner1 = new HashCodeCombiner();
|
||||
combiner1.AddDateTime(dt);
|
||||
|
||||
var combiner2 = new HashCodeCombiner();
|
||||
combiner2.AddDateTime(dt);
|
||||
|
||||
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
|
||||
combiner2.AddDateTime(DateTime.Now);
|
||||
|
||||
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HashCombiner_Test_File()
|
||||
{
|
||||
var dir = PrepareFolder();
|
||||
var file1Path = Path.Combine(dir.FullName, "hastest1.txt");
|
||||
File.Delete(file1Path);
|
||||
using (var file1 = File.CreateText(Path.Combine(dir.FullName, "hastest1.txt")))
|
||||
{
|
||||
file1.WriteLine("hello");
|
||||
}
|
||||
var file2Path = Path.Combine(dir.FullName, "hastest2.txt");
|
||||
File.Delete(file2Path);
|
||||
using (var file2 = File.CreateText(Path.Combine(dir.FullName, "hastest2.txt")))
|
||||
{
|
||||
//even though files are the same, the dates are different
|
||||
file2.WriteLine("hello");
|
||||
}
|
||||
|
||||
var combiner1 = new HashCodeCombiner();
|
||||
combiner1.AddFile(new FileInfo(file1Path));
|
||||
|
||||
var combiner2 = new HashCodeCombiner();
|
||||
combiner2.AddFile(new FileInfo(file1Path));
|
||||
|
||||
var combiner3 = new HashCodeCombiner();
|
||||
combiner3.AddFile(new FileInfo(file2Path));
|
||||
|
||||
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner3.GetCombinedHashCode());
|
||||
|
||||
combiner2.AddFile(new FileInfo(file2Path));
|
||||
|
||||
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HashCombiner_Test_Folder()
|
||||
{
|
||||
var dir = PrepareFolder();
|
||||
var file1Path = Path.Combine(dir.FullName, "hastest1.txt");
|
||||
File.Delete(file1Path);
|
||||
using (var file1 = File.CreateText(Path.Combine(dir.FullName, "hastest1.txt")))
|
||||
{
|
||||
file1.WriteLine("hello");
|
||||
}
|
||||
|
||||
//first test the whole folder
|
||||
var combiner1 = new HashCodeCombiner();
|
||||
combiner1.AddFolder(dir);
|
||||
|
||||
var combiner2 = new HashCodeCombiner();
|
||||
combiner2.AddFolder(dir);
|
||||
|
||||
Assert.AreEqual(combiner1.GetCombinedHashCode(), combiner2.GetCombinedHashCode());
|
||||
|
||||
//now add a file to the folder
|
||||
|
||||
var file2Path = Path.Combine(dir.FullName, "hastest2.txt");
|
||||
File.Delete(file2Path);
|
||||
using (var file2 = File.CreateText(Path.Combine(dir.FullName, "hastest2.txt")))
|
||||
{
|
||||
//even though files are the same, the dates are different
|
||||
file2.WriteLine("hello");
|
||||
}
|
||||
|
||||
var combiner3 = new HashCodeCombiner();
|
||||
combiner3.AddFolder(dir);
|
||||
|
||||
Assert.AreNotEqual(combiner1.GetCombinedHashCode(), combiner3.GetCombinedHashCode());
|
||||
}
|
||||
|
||||
public override void TestSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void TestTearDown()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ using Umbraco.Tests.BusinessLogic;
|
||||
|
||||
namespace Umbraco.Tests.IO
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture, RequiresSTA]
|
||||
internal abstract class AbstractFileSystemTests
|
||||
{
|
||||
protected IFileSystem _fileSystem;
|
||||
@@ -104,7 +104,7 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
_fileSystem.DeleteDirectory("test", true);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Can_Get_File_Dates()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,13 @@ namespace Umbraco.Tests.IO
|
||||
public class IOHelperTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void IOHelper_ResolveUrl()
|
||||
{
|
||||
var result = IOHelper.ResolveUrl("~/Scripts");
|
||||
Assert.AreEqual("/Scripts", result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for MapPath verifying that HttpContext method (which includes vdirs) matches non-HttpContext method
|
||||
///</summary>
|
||||
|
||||
@@ -9,14 +9,32 @@ using Umbraco.Tests.BusinessLogic;
|
||||
|
||||
namespace Umbraco.Tests.IO
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture, RequiresSTA]
|
||||
internal class PhysicalFileSystemTests : AbstractFileSystemTests
|
||||
{
|
||||
public PhysicalFileSystemTests()
|
||||
: base(new PhysicalFileSystem(AppDomain.CurrentDomain.BaseDirectory,
|
||||
: base(new PhysicalFileSystem(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FileSysTests"),
|
||||
"/Media/"))
|
||||
{ }
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FileSysTests");
|
||||
var files = Directory.GetFiles(path);
|
||||
foreach (var f in files)
|
||||
{
|
||||
File.Delete(f);
|
||||
}
|
||||
Directory.Delete(path, true);
|
||||
}
|
||||
|
||||
protected override string ConstructUrl(string path)
|
||||
{
|
||||
return "/Media/" + path;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
@@ -26,6 +27,17 @@ namespace Umbraco.Tests
|
||||
|
||||
var routingContext = GetRoutingContext("/test", 1234);
|
||||
UmbracoContext.Current = routingContext.UmbracoContext;
|
||||
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
Core.Configuration.UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Tests
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Tests
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -67,7 +68,8 @@ namespace Umbraco.Tests
|
||||
{"FALSE", false},
|
||||
{"False", false},
|
||||
{"false", false},
|
||||
{"0", false}
|
||||
{"0", false},
|
||||
{"", false}
|
||||
};
|
||||
|
||||
foreach (var testCase in testCases)
|
||||
@@ -79,6 +81,34 @@ namespace Umbraco.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestOnlyInFullTrust]
|
||||
public virtual void CanConvertStringToDateTime()
|
||||
{
|
||||
var dateTime = new DateTime(2012, 11, 10, 13, 14, 15);
|
||||
var testCases = new Dictionary<string, bool>
|
||||
{
|
||||
{"2012-11-10", true},
|
||||
{"2012/11/10", true},
|
||||
{"10/11/2012", true},
|
||||
{"11/10/2012", false},
|
||||
{"Sat 10, Nov 2012", true},
|
||||
{"Saturday 10, Nov 2012", true},
|
||||
{"Sat 10, November 2012", true},
|
||||
{"Saturday 10, November 2012", true},
|
||||
{"2012-11-10 13:14:15", true},
|
||||
{"", false}
|
||||
};
|
||||
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var result = testCase.Key.TryConvertTo<DateTime>();
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run once before each test in derived test fixtures.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,37 +1,44 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web.Compilation;
|
||||
using NUnit.Framework;
|
||||
using SqlCE4Umbraco;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using umbraco;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.MacroEngines;
|
||||
using umbraco.MacroEngines.Iron;
|
||||
using umbraco.businesslogic;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.editorControls;
|
||||
using umbraco.interfaces;
|
||||
using umbraco.uicontrols;
|
||||
using umbraco.cms;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class PluginManagerTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class PluginManagerTests
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
//TODO: Should probably update this so it only searches this assembly and add custom types to be found
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
//TODO: Should probably update this so it only searches this assembly and add custom types to be found
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
{
|
||||
this.GetType().Assembly,
|
||||
typeof(ApplicationStartupHandler).Assembly,
|
||||
@@ -47,132 +54,318 @@ namespace Umbraco.Tests
|
||||
typeof(System.Web.Mvc.ActionResult).Assembly,
|
||||
typeof(TypeFinder).Assembly,
|
||||
typeof(ISqlHelper).Assembly,
|
||||
typeof(DLRScriptingEngine).Assembly,
|
||||
typeof(ICultureDictionary).Assembly,
|
||||
typeof(UmbracoContext).Assembly,
|
||||
typeof(BaseDataType).Assembly
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Only_One_Type_List_Created()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
|
||||
var foundTypes2 = PluginManager.Current.ResolveFindMeTypes();
|
||||
Assert.AreEqual(1,
|
||||
PluginManager.Current.GetTypeLists()
|
||||
.Count(x => x.IsTypeList<IFindMe>(PluginManager.TypeResolutionKind.FindAllTypes)));
|
||||
}
|
||||
private DirectoryInfo PrepareFolder()
|
||||
{
|
||||
var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
|
||||
var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "PluginManager", Guid.NewGuid().ToString("N")));
|
||||
foreach (var f in dir.GetFiles())
|
||||
{
|
||||
f.Delete();
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Types()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
|
||||
Assert.AreEqual(2, foundTypes1.Count());
|
||||
}
|
||||
//[Test]
|
||||
//public void Scan_Vs_Load_Benchmark()
|
||||
//{
|
||||
// var pluginManager = new PluginManager(false);
|
||||
// var watch = new Stopwatch();
|
||||
// watch.Start();
|
||||
// for (var i = 0; i < 1000; i++)
|
||||
// {
|
||||
// var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// }
|
||||
// watch.Stop();
|
||||
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
|
||||
// watch.Start();
|
||||
// for (var i = 0; i < 1000; i++)
|
||||
// {
|
||||
// var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// }
|
||||
// watch.Stop();
|
||||
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
|
||||
// watch.Reset();
|
||||
// watch.Start();
|
||||
// for (var i = 0; i < 1000; i++)
|
||||
// {
|
||||
// var refreshers = pluginManager.ResolveTypes<ICacheRefresher>(false);
|
||||
// }
|
||||
// watch.Stop();
|
||||
// Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Attributed_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveAttributedTrees();
|
||||
Assert.AreEqual(27, trees.Count());
|
||||
}
|
||||
////NOTE: This test shows that Type.GetType is 100% faster than Assembly.Load(..).GetType(...) so we'll use that :)
|
||||
//[Test]
|
||||
//public void Load_Type_Benchmark()
|
||||
//{
|
||||
// var watch = new Stopwatch();
|
||||
// watch.Start();
|
||||
// for (var i = 0; i < 1000; i++)
|
||||
// {
|
||||
// var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null");
|
||||
// }
|
||||
// watch.Stop();
|
||||
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
|
||||
// watch.Reset();
|
||||
// watch.Start();
|
||||
// for (var i = 0; i < 1000; i++)
|
||||
// {
|
||||
// var type2 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
|
||||
// .GetType("umbraco.macroCacheRefresh");
|
||||
// var type3 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
|
||||
// .GetType("umbraco.templateCacheRefresh");
|
||||
// var type4 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
|
||||
// .GetType("umbraco.presentation.cache.MediaLibraryRefreshers");
|
||||
// var type5 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null")
|
||||
// .GetType("umbraco.presentation.cache.pageRefresher");
|
||||
// }
|
||||
// watch.Stop();
|
||||
// Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds);
|
||||
// watch.Reset();
|
||||
// watch.Start();
|
||||
// for (var i = 0; i < 1000; i++)
|
||||
// {
|
||||
// var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true);
|
||||
// }
|
||||
// watch.Stop();
|
||||
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Actions()
|
||||
{
|
||||
var actions = PluginManager.Current.ResolveActions();
|
||||
Assert.AreEqual(37, actions.Count());
|
||||
}
|
||||
[Test]
|
||||
public void Detect_Legacy_Plugin_File_List()
|
||||
{
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
var manager = new PluginManager(false);
|
||||
var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
|
||||
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<plugins>
|
||||
<baseType type=""umbraco.interfaces.ICacheRefresher"">
|
||||
<add type=""umbraco.macroCacheRefresh, umbraco, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null"" />
|
||||
</baseType>
|
||||
</plugins>");
|
||||
|
||||
[Test]
|
||||
public void Resolves_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveTrees();
|
||||
Assert.AreEqual(36, trees.Count());
|
||||
}
|
||||
Assert.IsTrue(manager.DetectLegacyPluginListFile());
|
||||
|
||||
[Test]
|
||||
public void Resolves_Applications()
|
||||
{
|
||||
var apps = PluginManager.Current.ResolveApplications();
|
||||
Assert.AreEqual(7, apps.Count());
|
||||
}
|
||||
File.Delete(filePath);
|
||||
|
||||
[Test]
|
||||
public void Resolves_Action_Handlers()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveActionHandlers();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
//now create a valid one
|
||||
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<plugins>
|
||||
<baseType type=""umbraco.interfaces.ICacheRefresher"" resolutionType=""FindAllTypes"">
|
||||
<add type=""umbraco.macroCacheRefresh, umbraco, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null"" />
|
||||
</baseType>
|
||||
</plugins>");
|
||||
|
||||
[Test]
|
||||
public void Resolves_DataTypes()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveDataTypes();
|
||||
Assert.AreEqual(37, types.Count());
|
||||
}
|
||||
Assert.IsFalse(manager.DetectLegacyPluginListFile());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_RazorDataTypeModels()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveRazorDataTypeModels();
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
[Test]
|
||||
public void Create_Cached_Plugin_File()
|
||||
{
|
||||
var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) };
|
||||
|
||||
[Test]
|
||||
public void Resolves_RestExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveRestExtensions();
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
var manager = new PluginManager(false);
|
||||
//yes this is silly, none of these types inherit from string, but this is just to test the xml file format
|
||||
manager.UpdateCachedPluginsFile<string>(types, PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
|
||||
[Test]
|
||||
public void Resolves_LegacyRestExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveLegacyRestExtensions();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
var plugins = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
var diffType = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAttributedTypes);
|
||||
|
||||
[Test]
|
||||
public void Resolves_XsltExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveXsltExtensions();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
Assert.IsTrue(plugins.Success);
|
||||
//this will be false since there is no cache of that type resolution kind
|
||||
Assert.IsFalse(diffType.Success);
|
||||
|
||||
[XsltExtension("Blah.Blah")]
|
||||
public class MyXsltExtension
|
||||
{
|
||||
Assert.AreEqual(3, plugins.Result.Count());
|
||||
var shouldContain = types.Select(x => x.AssemblyQualifiedName);
|
||||
//ensure they are all found
|
||||
Assert.IsTrue(plugins.Result.ContainsAll(shouldContain));
|
||||
}
|
||||
|
||||
}
|
||||
[Test]
|
||||
public void PluginHash_From_String()
|
||||
{
|
||||
var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture);
|
||||
var output = PluginManager.ConvertPluginsHashFromHex(s);
|
||||
Assert.AreNotEqual(0, output);
|
||||
}
|
||||
|
||||
[umbraco.presentation.umbracobase.RestExtension("Blah")]
|
||||
public class MyLegacyRestExtension
|
||||
{
|
||||
|
||||
}
|
||||
[Test]
|
||||
public void Get_Plugins_Hash()
|
||||
{
|
||||
//Arrange
|
||||
var dir = PrepareFolder();
|
||||
var d1 = dir.CreateSubdirectory("1");
|
||||
var d2 = dir.CreateSubdirectory("2");
|
||||
var d3 = dir.CreateSubdirectory("3");
|
||||
var d4 = dir.CreateSubdirectory("4");
|
||||
var f1 = new FileInfo(Path.Combine(d1.FullName, "test1.dll"));
|
||||
var f2 = new FileInfo(Path.Combine(d1.FullName, "test2.dll"));
|
||||
var f3 = new FileInfo(Path.Combine(d2.FullName, "test1.dll"));
|
||||
var f4 = new FileInfo(Path.Combine(d2.FullName, "test2.dll"));
|
||||
var f5 = new FileInfo(Path.Combine(d3.FullName, "test1.dll"));
|
||||
var f6 = new FileInfo(Path.Combine(d3.FullName, "test2.dll"));
|
||||
var f7 = new FileInfo(Path.Combine(d4.FullName, "test1.dll"));
|
||||
f1.CreateText().Close();
|
||||
f2.CreateText().Close();
|
||||
f3.CreateText().Close();
|
||||
f4.CreateText().Close();
|
||||
f5.CreateText().Close();
|
||||
f6.CreateText().Close();
|
||||
f7.CreateText().Close();
|
||||
var list1 = new[] { f1, f2, f3, f4, f5, f6 };
|
||||
var list2 = new[] { f1, f3, f5 };
|
||||
var list3 = new[] { f1, f3, f5, f7 };
|
||||
|
||||
[Umbraco.Web.BaseRest.RestExtension("Blah")]
|
||||
public class MyRestExtesion
|
||||
{
|
||||
|
||||
}
|
||||
//Act
|
||||
var hash1 = PluginManager.GetAssembliesHash(list1);
|
||||
var hash2 = PluginManager.GetAssembliesHash(list2);
|
||||
var hash3 = PluginManager.GetAssembliesHash(list3);
|
||||
|
||||
public interface IFindMe
|
||||
{
|
||||
//Assert
|
||||
Assert.AreNotEqual(hash1, hash2);
|
||||
Assert.AreNotEqual(hash1, hash3);
|
||||
Assert.AreNotEqual(hash2, hash3);
|
||||
|
||||
}
|
||||
Assert.AreEqual(hash1, PluginManager.GetAssembliesHash(list1));
|
||||
}
|
||||
|
||||
public class FindMe1 : IFindMe
|
||||
{
|
||||
[Test]
|
||||
public void Ensure_Only_One_Type_List_Created()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
|
||||
var foundTypes2 = PluginManager.Current.ResolveFindMeTypes();
|
||||
Assert.AreEqual(1,
|
||||
PluginManager.Current.GetTypeLists()
|
||||
.Count(x => x.IsTypeList<IFindMe>(PluginManager.TypeResolutionKind.FindAllTypes)));
|
||||
}
|
||||
|
||||
}
|
||||
[Test]
|
||||
public void Resolves_Types()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
|
||||
Assert.AreEqual(2, foundTypes1.Count());
|
||||
}
|
||||
|
||||
public class FindMe2 : IFindMe
|
||||
{
|
||||
[Test]
|
||||
public void Resolves_Attributed_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveAttributedTrees();
|
||||
Assert.AreEqual(27, trees.Count());
|
||||
}
|
||||
|
||||
}
|
||||
[Test]
|
||||
public void Resolves_Actions()
|
||||
{
|
||||
var actions = PluginManager.Current.ResolveActions();
|
||||
Assert.AreEqual(37, actions.Count());
|
||||
}
|
||||
|
||||
}
|
||||
[Test]
|
||||
public void Resolves_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveTrees();
|
||||
Assert.AreEqual(36, trees.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Applications()
|
||||
{
|
||||
var apps = PluginManager.Current.ResolveApplications();
|
||||
Assert.AreEqual(7, apps.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Action_Handlers()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveActionHandlers();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_DataTypes()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveDataTypes();
|
||||
Assert.AreEqual(37, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_RazorDataTypeModels()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveRazorDataTypeModels();
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_RestExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveRestExtensions();
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_LegacyRestExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveLegacyRestExtensions();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_XsltExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveXsltExtensions();
|
||||
Assert.AreEqual(1, types.Count());
|
||||
}
|
||||
|
||||
[XsltExtension("Blah.Blah")]
|
||||
public class MyXsltExtension
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[umbraco.presentation.umbracobase.RestExtension("Blah")]
|
||||
public class MyLegacyRestExtension
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Umbraco.Web.BaseRest.RestExtension("Blah")]
|
||||
public class MyRestExtesion
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class FindMe1 : IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class FindMe2 : IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.PropertyEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class PropertyEditorValueConverterTests
|
||||
{
|
||||
[Test]
|
||||
public void CanConvertDatePickerPropertyEditor()
|
||||
{
|
||||
var converter = new DatePickerPropertyEditorValueConverter();
|
||||
var dateTime = new DateTime(2012, 11, 10, 13, 14, 15);
|
||||
var testCases = new Dictionary<string, bool>
|
||||
{
|
||||
{"2012-11-10", true},
|
||||
{"2012/11/10", true},
|
||||
{"10/11/2012", true},
|
||||
{"11/10/2012", false},
|
||||
{"Sat 10, Nov 2012", true},
|
||||
{"Saturday 10, Nov 2012", true},
|
||||
{"Sat 10, November 2012", true},
|
||||
{"Saturday 10, November 2012", true},
|
||||
{"2012-11-10 13:14:15", true},
|
||||
{"", false}
|
||||
};
|
||||
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var result = converter.ConvertPropertyValue(testCase.Key);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(DateTime.Equals(dateTime.Date, ((DateTime)result.Result).Date), testCase.Value);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanConvertYesNoPropertyEditor()
|
||||
{
|
||||
var converter = new YesNoPropertyEditorValueConverter();
|
||||
var testCases = new Dictionary<string, bool>
|
||||
{
|
||||
{"TRUE", true},
|
||||
{"True", true},
|
||||
{"true", true},
|
||||
{"1", true},
|
||||
{"FALSE", false},
|
||||
{"False", false},
|
||||
{"false", false},
|
||||
{"0", false},
|
||||
{"", false}
|
||||
};
|
||||
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var result = converter.ConvertPropertyValue(testCase.Key);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(testCase.Value, result.Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,710 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
[TestFixture]
|
||||
public abstract class DynamicDocumentTestsBase<TDocument, TDocumentList> : PublishedContentTestBase
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
}
|
||||
|
||||
protected override bool RequiresDbSetup
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
protected override string GetXmlContent(int templateId)
|
||||
{
|
||||
return @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<!DOCTYPE root[
|
||||
<!ELEMENT Home ANY>
|
||||
<!ATTLIST Home id ID #REQUIRED>
|
||||
<!ELEMENT CustomDocument ANY>
|
||||
<!ATTLIST CustomDocument id ID #REQUIRED>
|
||||
]>
|
||||
<root id=""-1"">
|
||||
<Home id=""1046"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-06-12T14:13:17"" updateDate=""2012-07-20T18:50:43"" nodeName=""Home"" urlName=""home"" writerName=""admin"" creatorName=""admin"" path=""-1,1046"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
<siteTitle><![CDATA[This is my site]]></siteTitle>
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
|
||||
<content><![CDATA[<div>This is some content</div>]]></content>
|
||||
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
|
||||
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
|
||||
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
|
||||
</Home>
|
||||
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
|
||||
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
|
||||
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
|
||||
<content><![CDATA[some content]]></content>
|
||||
<blah><![CDATA[some content]]></blah>
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
</Home>
|
||||
</Home>
|
||||
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
|
||||
</Home>
|
||||
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
|
||||
<selectedNodes><![CDATA[1172,1176,1173]]></selectedNodes>
|
||||
<CustomDocument id=""5555"" parentID=""1046"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""0"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444,5555"" isDoc="""">
|
||||
</CustomDocument>
|
||||
</CustomDocument>
|
||||
</Home>
|
||||
<CustomDocument id=""1172"" parentID=""-1"" level=""1"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1172"" isDoc="""" />
|
||||
</root>";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dynamic node/document to run tests against
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract dynamic GetDynamicNode(int id);
|
||||
|
||||
[Test]
|
||||
public void Recursive_Property()
|
||||
{
|
||||
var doc = GetDynamicNode(1174);
|
||||
var prop = doc.GetProperty("siteTitle", true);
|
||||
Assert.IsNotNull(prop);
|
||||
Assert.AreEqual("This is my site", prop.Value);
|
||||
prop = doc.GetProperty("_siteTitle"); //test with underscore prefix
|
||||
Assert.IsNotNull(prop);
|
||||
Assert.AreEqual("This is my site", prop.Value);
|
||||
Assert.AreEqual("This is my site", doc._siteTitle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the internal instance level caching of returning properties
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://issues.umbraco.org/issue/U4-1824
|
||||
/// http://issues.umbraco.org/issue/U4-1825
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void Can_Return_Property_And_Value()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsTrue(doc.HasProperty("umbracoUrlAlias"));
|
||||
var prop = doc.GetProperty("umbracoUrlAlias");
|
||||
Assert.IsNotNull(prop);
|
||||
Assert.AreEqual("page2/alias, 2ndpagealias", prop.Value);
|
||||
Assert.AreEqual("page2/alias, 2ndpagealias", doc.umbracoUrlAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the IsLast method with the result set from a Where statement
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Is_Last_From_Where_Filter()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
foreach (var d in doc.Children.Where("Visible"))
|
||||
{
|
||||
if (d.Id != 1178)
|
||||
{
|
||||
Assert.IsFalse(d.IsLast());
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(d.IsLast());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Single()
|
||||
{
|
||||
var doc = GetDynamicNode(4444);
|
||||
|
||||
var result = doc.Children().Single();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(5555, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Single_With_Query()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var result = doc.Children().Single("id==1175");
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1175, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void First()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var result = doc.Children().First();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1174, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void First_With_Query()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var result = doc.Children().First("blah==\"some content\"");
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1176, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_User_Property_Value()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var result = (IEnumerable<dynamic>)doc.Children().Where("blah==\"some content\"");
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual(1176, result.Single().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void String_ContainsValue_Extension_Method()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var paramVals = new Dictionary<string, object> { { "searchId", 1173 } }; //this is an integer value
|
||||
var result = doc.Children()
|
||||
.Where("selectedNodes.ContainsValue(searchId)", paramVals) //call an extension method
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
|
||||
//don't find!
|
||||
paramVals = new Dictionary<string, object> { { "searchId", 1111777 } };
|
||||
result = doc.Children()
|
||||
.Where("selectedNodes.ContainsValue(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsTrue(result.GetType() == typeof(DynamicNull) || result.GetType() == typeof(umbraco.MacroEngines.DynamicNull));
|
||||
//Assert.AreEqual(typeof(DynamicNull), result.GetType());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void String_Contains_Method()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var paramVals = new Dictionary<string, object> { { "searchId", "1173" } };
|
||||
var result = doc.Children()
|
||||
.Where("selectedNodes.Contains(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
|
||||
//don't find!
|
||||
paramVals = new Dictionary<string, object> { { "searchId", "1aaa173" } };
|
||||
result = doc.Children()
|
||||
.Where("selectedNodes.Contains(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsTrue(result.GetType() == typeof(DynamicNull) || result.GetType() == typeof(umbraco.MacroEngines.DynamicNull));
|
||||
//Assert.AreEqual(typeof (DynamicNull), result.GetType());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void String_Split_Method()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var paramVals = new Dictionary<string, object>
|
||||
{
|
||||
{ "splitTerm", new char[] { ',' } },
|
||||
{ "splitOptions", StringSplitOptions.RemoveEmptyEntries }
|
||||
};
|
||||
var result = doc.Children()
|
||||
.Where("selectedNodes.Split(splitTerm, splitOptions).Length == 3", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
}
|
||||
|
||||
[Ignore("We are ignoring this test because currently our ExpressionParser class cannot deal with this... it needs some serious TLC but it is very complex.")]
|
||||
[Test]
|
||||
public void Complex_Linq()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
|
||||
var paramVals = new Dictionary<string, object> { { "splitTerm", new char[] { ',' } }, { "searchId", "1173" } };
|
||||
var result = doc.Ancestors().OrderBy("level")
|
||||
.Single()
|
||||
.Descendants()
|
||||
.Where("selectedNodes != null && selectedNodes != String.Empty && selectedNodes.Split(splitTerm).Contains(searchId)", paramVals)
|
||||
.FirstOrDefault();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(4444, result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Index()
|
||||
{
|
||||
var doc = GetDynamicNode(1173);
|
||||
Assert.AreEqual(0, doc.Index());
|
||||
doc = GetDynamicNode(1176);
|
||||
Assert.AreEqual(3, doc.Index());
|
||||
doc = GetDynamicNode(1177);
|
||||
Assert.AreEqual(1, doc.Index());
|
||||
doc = GetDynamicNode(1178);
|
||||
Assert.AreEqual(2, doc.Index());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public virtual void Is_First_Root_Nodes()
|
||||
{
|
||||
var doc = GetDynamicNode(1046); //test root nodes
|
||||
Assert.IsTrue(doc.IsFirst());
|
||||
doc = GetDynamicNode(1172);
|
||||
Assert.IsFalse(doc.IsFirst());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_First()
|
||||
{
|
||||
var doc = GetDynamicNode(1173); //test normal nodes
|
||||
Assert.IsTrue(doc.IsFirst());
|
||||
doc = GetDynamicNode(1175);
|
||||
Assert.IsFalse(doc.IsFirst());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public virtual void Is_Not_First_Root_Nodes()
|
||||
{
|
||||
var doc = GetDynamicNode(1046); //test root nodes
|
||||
Assert.IsFalse(doc.IsNotFirst());
|
||||
doc = GetDynamicNode(1172);
|
||||
Assert.IsTrue(doc.IsNotFirst());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Not_First()
|
||||
{
|
||||
var doc = GetDynamicNode(1173); //test normal nodes
|
||||
Assert.IsFalse(doc.IsNotFirst());
|
||||
doc = GetDynamicNode(1175);
|
||||
Assert.IsTrue(doc.IsNotFirst());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public virtual void Is_Position_Root_Nodes()
|
||||
{
|
||||
var doc = GetDynamicNode(1046); //test root nodes
|
||||
Assert.IsTrue(doc.IsPosition(0));
|
||||
doc = GetDynamicNode(1172);
|
||||
Assert.IsTrue(doc.IsPosition(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Position()
|
||||
{
|
||||
var doc = GetDynamicNode(1173); //test normal nodes
|
||||
Assert.IsTrue(doc.IsPosition(0));
|
||||
doc = GetDynamicNode(1175);
|
||||
Assert.IsTrue(doc.IsPosition(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_GroupBy_DocumentTypeAlias()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var found1 = doc.Children.GroupBy("DocumentTypeAlias");
|
||||
|
||||
var casted = (IEnumerable<IGrouping<object, dynamic>>)(found1);
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
Assert.AreEqual(2, casted.Single(x => x.Key.ToString() == "Home").Count());
|
||||
Assert.AreEqual(1, casted.Single(x => x.Key.ToString() == "CustomDocument").Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Where_DocumentTypeAlias()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var found1 = doc.Children.Where("DocumentTypeAlias == \"CustomDocument\"");
|
||||
var found2 = doc.Children.Where("DocumentTypeAlias == \"Home\"");
|
||||
|
||||
Assert.AreEqual(1, found1.Count());
|
||||
Assert.AreEqual(2, found2.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Where_NodeTypeAlias()
|
||||
{
|
||||
var doc = GetDynamicNode(1046);
|
||||
|
||||
var found1 = doc.Children.Where("NodeTypeAlias == \"CustomDocument\"");
|
||||
var found2 = doc.Children.Where("NodeTypeAlias == \"Home\"");
|
||||
|
||||
Assert.AreEqual(1, found1.Count());
|
||||
Assert.AreEqual(2, found2.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Order_By_Update_Date()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var ordered = asDynamic.Children.OrderBy("UpdateDate");
|
||||
var casted = (IEnumerable<TDocument>)ordered;
|
||||
|
||||
var correctOrder = new[] { 1178, 1177, 1174, 1176 };
|
||||
for (var i = 0; i < correctOrder.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Order_By_Update_Date_Descending()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var ordered = asDynamic.Children.OrderBy("UpdateDate desc");
|
||||
var casted = (IEnumerable<TDocument>)ordered;
|
||||
|
||||
var correctOrder = new[] { 1176, 1174, 1177, 1178 };
|
||||
for (var i = 0; i < correctOrder.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(correctOrder[i], ((dynamic)casted.ElementAt(i)).Id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasProperty()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var hasProp = asDynamic.HasProperty("umbracoUrlAlias");
|
||||
|
||||
Assert.AreEqual(true, (bool)hasProp);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Skip()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var skip = asDynamic.Children.Skip(2);
|
||||
var casted = (IEnumerable<TDocument>)skip;
|
||||
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1178, 1176 }));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HasValue()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var hasValue = asDynamic.HasValue("umbracoUrlAlias");
|
||||
var noValue = asDynamic.HasValue("blahblahblah");
|
||||
|
||||
Assert.IsTrue(hasValue);
|
||||
Assert.IsFalse(noValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Take()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var take = asDynamic.Children.Take(2);
|
||||
var casted = (IEnumerable<TDocument>)take;
|
||||
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
Assert.IsTrue(casted.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1177 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors_Where_Visible()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
var whereVisible = asDynamic.Ancestors().Where("Visible");
|
||||
var casted = (IEnumerable<TDocument>)whereVisible;
|
||||
|
||||
Assert.AreEqual(1, casted.Count());
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Visible()
|
||||
{
|
||||
var asDynamicHidden = GetDynamicNode(1046);
|
||||
var asDynamicVisible = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsFalse(asDynamicHidden.Visible);
|
||||
Assert.IsTrue(asDynamicVisible.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_TinyMCE_Converted_Type_User_Property()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(asDynamic.Content.GetType()));
|
||||
Assert.AreEqual("<div>This is some content</div>", asDynamic.Content.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Children_With_Pluralized_Alias()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Action<object> doAssert = d =>
|
||||
{
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(d));
|
||||
var casted = (IEnumerable<TDocument>)d;
|
||||
Assert.AreEqual(2, casted.Count());
|
||||
};
|
||||
|
||||
doAssert(asDynamic.Homes); //pluralized alias
|
||||
doAssert(asDynamic.homes); //pluralized alias
|
||||
doAssert(asDynamic.CustomDocuments); //pluralized alias
|
||||
doAssert(asDynamic.customDocuments); //pluralized alias
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPropertyValue_Non_Reflected()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("creatorName"));
|
||||
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.GetPropertyValue("CreatorName"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPropertyValue_Reflected()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@creatorName"));
|
||||
Assert.AreEqual("admin", asDynamic.GetPropertyValue("@CreatorName"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_User_Property_With_Same_Name_As_Member_Property()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
Assert.AreEqual("Custom data with same property name as the member name", asDynamic.creatorName);
|
||||
|
||||
//because CreatorName is defined on DynamicNode, it will not return the user defined property
|
||||
Assert.AreEqual("admin", asDynamic.CreatorName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Member_Property()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Assert.AreEqual((int)2, (int)asDynamic.Level);
|
||||
Assert.AreEqual((int)2, (int)asDynamic.level);
|
||||
|
||||
Assert.AreEqual((int)1046, (int)asDynamic.ParentId);
|
||||
Assert.AreEqual((int)1046, (int)asDynamic.parentId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Children()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var children = asDynamic.Children;
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(children));
|
||||
|
||||
var childrenAsList = asDynamic.ChildrenAsList; //test ChildrenAsList too
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IEnumerable>(childrenAsList));
|
||||
|
||||
var castChildren = (IEnumerable<TDocument>)children;
|
||||
Assert.AreEqual(4, castChildren.Count());
|
||||
|
||||
var castChildrenAsList = (IEnumerable<TDocument>)childrenAsList;
|
||||
Assert.AreEqual(4, castChildrenAsList.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestor_Or_Self()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.AncestorOrSelf();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int)1046, (int)result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors_Or_Self()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
var result = asDynamic.AncestorsOrSelf();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(3, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1174, 1173, 1046 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1174);
|
||||
|
||||
var result = asDynamic.Ancestors();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(2, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1046 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants_Or_Self()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1046);
|
||||
|
||||
var result = asDynamic.DescendantsOrSelf();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(9, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1046, 1173, 1174, 1176, 1175, 4444 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1046);
|
||||
|
||||
var result = asDynamic.Descendants();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
var list = (IEnumerable<TDocument>)result;
|
||||
Assert.AreEqual(8, list.Count());
|
||||
Assert.IsTrue(list.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Up()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.Up();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int)1046, (int)result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Down()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.Down();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int)1174, (int)result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Next()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
var result = asDynamic.Next();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int)1175, (int)result.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Next_Without_Sibling()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1176);
|
||||
|
||||
Assert.IsNull(asDynamic.Next());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Previous_Without_Sibling()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1173);
|
||||
|
||||
Assert.IsNull(asDynamic.Previous());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Previous()
|
||||
{
|
||||
var asDynamic = GetDynamicNode(1176);
|
||||
|
||||
var result = asDynamic.Previous();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int)1178, (int)result.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods used in tests
|
||||
/// </summary>
|
||||
public static class TestExtensionMethods
|
||||
{
|
||||
public static bool ContainsValue(this string s, int val)
|
||||
{
|
||||
return s.Contains(val.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using umbraco.IO;
|
||||
using umbraco.MacroEngines;
|
||||
using umbraco.NodeFactory;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
[TestFixture]
|
||||
public class DynamicNodeTests : DynamicDocumentTestsBase<DynamicNode, DynamicNodeList>
|
||||
{
|
||||
protected override bool RequiresDbSetup
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
//copy the umbraco settings file over
|
||||
var currDir = new DirectoryInfo(TestHelper.CurrentAssemblyDirectory);
|
||||
File.Copy(
|
||||
currDir.Parent.Parent.Parent.GetDirectories("Umbraco.Web.UI")
|
||||
.First()
|
||||
.GetDirectories("config").First()
|
||||
.GetFiles("umbracoSettings.Release.config").First().FullName,
|
||||
Path.Combine(currDir.Parent.Parent.FullName, "config", "umbracoSettings.config"),
|
||||
true);
|
||||
|
||||
UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
{
|
||||
typeof(DynamicNode).Assembly
|
||||
};
|
||||
|
||||
//need to specify a custom callback for unit tests
|
||||
DynamicNode.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
|
||||
{
|
||||
if (propertyAlias == "content")
|
||||
{
|
||||
//return the rte type id
|
||||
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
|
||||
}
|
||||
return Guid.Empty;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("This test will never work unless DynamicNode is refactored a lot in order to get a list of root nodes since root nodes don't have a parent to look up")]
|
||||
public override void Is_First_Root_Nodes()
|
||||
{
|
||||
base.Is_First_Root_Nodes();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("This test will never work unless DynamicNode is refactored a lot in order to get a list of root nodes since root nodes don't have a parent to look up")]
|
||||
public override void Is_Not_First_Root_Nodes()
|
||||
{
|
||||
base.Is_Not_First_Root_Nodes();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("This test will never work unless DynamicNode is refactored a lot in order to get a list of root nodes since root nodes don't have a parent to look up")]
|
||||
public override void Is_Position_Root_Nodes()
|
||||
{
|
||||
base.Is_Position_Root_Nodes();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
PluginManager.Current.AssembliesToScan = null;
|
||||
}
|
||||
|
||||
protected override dynamic GetDynamicNode(int id)
|
||||
{
|
||||
//var template = Template.MakeNew("test", new User(0));
|
||||
//var ctx = GetUmbracoContext("/test", template.Id);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var contentStore = new DefaultPublishedContentStore();
|
||||
var node = new DynamicNode(
|
||||
new DynamicBackingItem(
|
||||
new Node(ctx.GetXml().SelectSingleNode("//*[@id='" + id + "' and @isDoc]"))));
|
||||
Assert.IsNotNull(node);
|
||||
return (dynamic)node;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -1,9 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
public static class DynamicPublishedContentCustomExtensionMethods
|
||||
{
|
||||
+3
-41
@@ -1,61 +1,22 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.Routing;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.cms.businesslogic;
|
||||
using umbraco.cms.businesslogic.template;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture]
|
||||
public class DynamicPublishedContentTests : DynamicDocumentTestsBase<DynamicPublishedContent, DynamicPublishedContentList>
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
|
||||
new[]
|
||||
{
|
||||
typeof(DatePickerPropertyEditorValueConverter),
|
||||
typeof(TinyMcePropertyEditorValueConverter),
|
||||
typeof(YesNoPropertyEditorValueConverter)
|
||||
});
|
||||
|
||||
//need to specify a custom callback for unit tests
|
||||
DynamicPublishedContent.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
|
||||
{
|
||||
if (propertyAlias == "content")
|
||||
{
|
||||
//return the rte type id
|
||||
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
|
||||
}
|
||||
return Guid.Empty;
|
||||
};
|
||||
|
||||
var rCtx = GetRoutingContext("/test", 1234);
|
||||
UmbracoContext.Current = rCtx.UmbracoContext;
|
||||
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
PropertyEditorValueConvertersResolver.Reset();
|
||||
PublishedContentStoreResolver.Reset();
|
||||
UmbracoContext.Current = null;
|
||||
}
|
||||
|
||||
internal DynamicPublishedContent GetNode(int id)
|
||||
@@ -86,6 +47,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
Assert.AreEqual("Hello world!" + 123 + false, asDynamic.DynamicDocumentMultiParam("Hello world!", 123, false));
|
||||
Assert.AreEqual("Hello world!" + 123 + false, asDynamic.Children.DynamicDocumentListMultiParam("Hello world!", 123, false));
|
||||
Assert.AreEqual("Hello world!" + 123 + false, asDynamic.Children.DynamicDocumentEnumerableMultiParam("Hello world!", 123, false));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.CSharp.RuntimeBinder;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
[TestFixture]
|
||||
public class DynamicXmlTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Custom_Extension_Method_Legacy()
|
||||
{
|
||||
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
|
||||
var typedXml = new global::umbraco.MacroEngines.DynamicXml(xml);
|
||||
dynamic dynamicXml = typedXml;
|
||||
|
||||
//we haven't explicitly defined ElementAt so this will dynamically invoke this method
|
||||
var element = dynamicXml.ElementAt(0);
|
||||
|
||||
Assert.AreEqual("1057", Enumerable.First(element.BaseElement.Elements()).Attribute("id").Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Custom_Extension_Method()
|
||||
{
|
||||
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
|
||||
var typedXml = new DynamicXml(xml);
|
||||
|
||||
dynamic dynamicXml = typedXml;
|
||||
|
||||
//we haven't explicitly defined ElementAt so this will dynamically invoke this method
|
||||
var element = dynamicXml.ElementAt(0);
|
||||
|
||||
Assert.AreEqual("1057", Enumerable.First(element.BaseElement.Elements()).Attribute("id").Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Take_Legacy()
|
||||
{
|
||||
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
|
||||
var typedXml = new global::umbraco.MacroEngines.DynamicXml(xml);
|
||||
dynamic dynamicXml = typedXml;
|
||||
var typedTaken = typedXml.Take(1);
|
||||
var dynamicTaken = dynamicXml.Take(1);
|
||||
|
||||
Assert.AreEqual(1, typedTaken.Count());
|
||||
Assert.AreEqual(1, Enumerable.Count(dynamicTaken));
|
||||
|
||||
Assert.AreEqual("1057", typedTaken.ElementAt(0).BaseElement.Elements().First().Attribute("id").Value);
|
||||
Assert.AreEqual("1057", Enumerable.First(Enumerable.ElementAt(dynamicTaken, 0).BaseElement.Elements()).Attribute("id").Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Take()
|
||||
{
|
||||
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
|
||||
var typedXml = new DynamicXml(xml);
|
||||
dynamic dynamicXml = typedXml;
|
||||
var typedTaken = typedXml.Take(1);
|
||||
var dynamicTaken = dynamicXml.Take(1);
|
||||
|
||||
Assert.AreEqual(1, typedTaken.Count());
|
||||
Assert.AreEqual(1, Enumerable.Count(dynamicTaken));
|
||||
|
||||
Assert.AreEqual("1057", typedTaken.ElementAt(0).BaseElement.Elements().First().Attribute("id").Value);
|
||||
Assert.AreEqual("1057", Enumerable.First(Enumerable.ElementAt(dynamicTaken, 0).BaseElement.Elements()).Attribute("id").Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Legacy_Objects_Are_Returned()
|
||||
{
|
||||
var xml = "<DAMP fullMedia=\"\"><mediaItem><Image id=\"1057\" version=\"d58d5c16-153e-4896-892f-a722e45a69af\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:55:29\" updateDate=\"2012-11-05T16:55:44\" nodeName=\"test12\" urlName=\"test12\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1057\"><umbracoFile>/media/54/tulips.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>620888</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:55:34\"><crop name=\"thumbCrop\" x=\"154\" y=\"1\" x2=\"922\" y2=\"768\" url=\"/media/54/tulips_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem><mediaItem><Image id=\"1055\" version=\"4df1f08a-3552-45f2-b4bf-fa980c762f4a\" parentID=\"-1\" level=\"1\" writerID=\"0\" nodeType=\"1032\" template=\"0\" sortOrder=\"1\" createDate=\"2012-11-05T16:29:58\" updateDate=\"2012-11-05T16:30:27\" nodeName=\"Test\" urlName=\"test\" writerName=\"admin\" nodeTypeAlias=\"Image\" path=\"-1,1055\"><umbracoFile>/media/41/hydrangeas.jpg</umbracoFile><umbracoWidth>1024</umbracoWidth><umbracoHeight>768</umbracoHeight><umbracoBytes>595284</umbracoBytes><umbracoExtension>jpg</umbracoExtension><newsCrops><crops date=\"2012-11-05T16:30:18\"><crop name=\"thumbCrop\" x=\"133\" y=\"0\" x2=\"902\" y2=\"768\" url=\"/media/41/hydrangeas_thumbCrop.jpg\" /></crops></newsCrops></Image></mediaItem></DAMP>";
|
||||
var mediaItems = new global::umbraco.MacroEngines.DynamicXml(xml);
|
||||
//Debug.WriteLine("full xml = {0}", mediaItems.ToXml());
|
||||
|
||||
if (mediaItems.Count() != 0)
|
||||
{
|
||||
foreach (dynamic item in mediaItems)
|
||||
{
|
||||
Type itemType = item.GetType();
|
||||
Debug.WriteLine("item type = {0}", itemType);
|
||||
dynamic image = item.Image;
|
||||
|
||||
Type imageType = image.GetType();
|
||||
Debug.WriteLine("image type = {0}", imageType);
|
||||
|
||||
//ensure they are the same
|
||||
Assert.AreEqual(itemType, imageType);
|
||||
|
||||
//ensure they are legacy
|
||||
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), itemType);
|
||||
Assert.AreEqual(typeof(global::umbraco.MacroEngines.DynamicXml), imageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the current Core class
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Find_Test_Core_Class()
|
||||
{
|
||||
RunFindTest(x => new DynamicXml(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the macroEngines legacy class
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Find_Test_Legacy_Class()
|
||||
{
|
||||
RunFindTest(x => new global::umbraco.MacroEngines.DynamicXml(x));
|
||||
}
|
||||
|
||||
private void RunFindTest(Func<string, dynamic> getDynamicXml)
|
||||
{
|
||||
var xmlstring = @"<test>
|
||||
<item id='1' name='test 1' value='found 1'/>
|
||||
<item id='2' name='test 2' value='found 2'/>
|
||||
<item id='3' name='test 3' value='found 3'/>
|
||||
</test>";
|
||||
|
||||
dynamic dXml = getDynamicXml(xmlstring);
|
||||
|
||||
var result1 = dXml.Find("@name", "test 1");
|
||||
var result2 = dXml.Find("@name", "test 2");
|
||||
var result3 = dXml.Find("@name", "test 3");
|
||||
var result4 = dXml.Find("@name", "dont find");
|
||||
|
||||
Assert.AreEqual("found 1", result1.value);
|
||||
Assert.AreEqual("found 2", result2.value);
|
||||
Assert.AreEqual("found 3", result3.value);
|
||||
Assert.Throws<RuntimeBinderException>(() =>
|
||||
{
|
||||
//this will throw because result4 is not found
|
||||
var temp = result4.value;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Lucene.Net.Documents;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Tests.TestHelpers.ExamineHelpers;
|
||||
using umbraco.MacroEngines;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
public class LegacyExamineBackedMediaTests : PublishedContentTestBase
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
UmbracoSettings.ForceSafeAliases = true;
|
||||
UmbracoSettings.UmbracoLibraryCacheDuration = 1800;
|
||||
UmbracoSettings.ForceSafeAliases = true;
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Children_Are_Sorted()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var searcher = indexInit.GetUmbracoSearcher(newIndexFolder);
|
||||
var result = searcher.Search(searcher.CreateSearchCriteria().Id(1111).Compile());
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1, result.TotalItemCount);
|
||||
|
||||
var searchItem = result.First();
|
||||
var backedMedia = new ExamineBackedMedia(searchItem, indexer, searcher);
|
||||
var children = backedMedia.ChildrenAsList.Value;
|
||||
|
||||
var currSort = 0;
|
||||
for (var i = 0; i < children.Count(); i++)
|
||||
{
|
||||
Assert.GreaterOrEqual(children[i].SortOrder, currSort);
|
||||
currSort = children[i].SortOrder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Result_Has_All_Values()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var searcher = indexInit.GetUmbracoSearcher(newIndexFolder);
|
||||
var result = searcher.Search(searcher.CreateSearchCriteria().Id(1111).Compile());
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(1, result.TotalItemCount);
|
||||
|
||||
var searchItem = result.First();
|
||||
var backedMedia = new ExamineBackedMedia(searchItem, indexer, searcher);
|
||||
|
||||
Assert.AreEqual(searchItem.Id, backedMedia.Id);
|
||||
Assert.AreEqual(searchItem.Fields["sortOrder"], backedMedia.SortOrder.ToString());
|
||||
Assert.AreEqual(searchItem.Fields["urlName"], backedMedia.UrlName);
|
||||
Assert.AreEqual(DateTools.StringToDate(searchItem.Fields["createDate"]), backedMedia.CreateDate);
|
||||
Assert.AreEqual(DateTools.StringToDate(searchItem.Fields["updateDate"]), backedMedia.UpdateDate);
|
||||
Assert.AreEqual(Guid.Parse(searchItem.Fields["version"]), backedMedia.Version);
|
||||
Assert.AreEqual(searchItem.Fields["level"], backedMedia.Level.ToString());
|
||||
Assert.AreEqual(searchItem.Fields["writerID"], backedMedia.WriterID.ToString());
|
||||
Assert.AreEqual(searchItem.Fields["writerID"], backedMedia.CreatorID.ToString()); //there's only writerId in the xml
|
||||
Assert.AreEqual(searchItem.Fields["writerName"], backedMedia.CreatorName);
|
||||
Assert.AreEqual(searchItem.Fields["writerName"], backedMedia.WriterName); //tehre's only writer name in the xml
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Unit tests for IPublishedContent and extensions
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base class for tests for published content and published media
|
||||
/// </summary>
|
||||
public abstract class PublishedContentTestBase : BaseRoutingTest
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
UmbracoSettings.SettingsFilePath = Core.IO.IOHelper.MapPath(Core.IO.SystemDirectories.Config + Path.DirectorySeparatorChar, false);
|
||||
|
||||
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
|
||||
new[]
|
||||
{
|
||||
typeof(DatePickerPropertyEditorValueConverter),
|
||||
typeof(TinyMcePropertyEditorValueConverter),
|
||||
typeof(YesNoPropertyEditorValueConverter)
|
||||
});
|
||||
|
||||
//need to specify a custom callback for unit tests
|
||||
PublishedContentHelper.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
|
||||
{
|
||||
if (propertyAlias == "content")
|
||||
{
|
||||
//return the rte type id
|
||||
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
|
||||
}
|
||||
return Guid.Empty;
|
||||
};
|
||||
|
||||
var rCtx = GetRoutingContext("/test", 1234);
|
||||
UmbracoContext.Current = rCtx.UmbracoContext;
|
||||
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
|
||||
PublishedMediaStoreResolver.Current = new PublishedMediaStoreResolver(new DefaultPublishedMediaStore());
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
PropertyEditorValueConvertersResolver.Reset();
|
||||
PublishedContentStoreResolver.Reset();
|
||||
PublishedMediaStoreResolver.Reset();
|
||||
UmbracoContext.Current = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+155
-59
@@ -1,20 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the typed extension methods on IPublishedContent the same way we test the dynamic ones
|
||||
/// Tests the methods on IPublishedContent using the DefaultPublishedContentStore
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class PublishedContentTests : BaseWebTest
|
||||
public class PublishedContentTests : PublishedContentTestBase
|
||||
{
|
||||
protected override bool RequiresDbSetup
|
||||
{
|
||||
@@ -35,23 +36,24 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
|
||||
<content><![CDATA[<div>This is some content</div>]]></content>
|
||||
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
|
||||
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
|
||||
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
|
||||
<creatorName><![CDATA[Custom data with same property name as the member name]]></creatorName>
|
||||
</Home>
|
||||
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
|
||||
</Home>
|
||||
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
|
||||
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
|
||||
<Home id=""1176"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-20T18:08:08"" updateDate=""2012-07-20T19:10:52"" nodeName=""Sub 3"" urlName=""sub-3"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1176"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
</Home>
|
||||
<CustomDocument id=""1177"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""custom sub 1"" urlName=""custom-sub-1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1177"" isDoc="""" />
|
||||
<CustomDocument id=""1178"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-16T14:23:35"" nodeName=""custom sub 2"" urlName=""custom-sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1178"" isDoc="""" />
|
||||
</Home>
|
||||
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
|
||||
<Home id=""1175"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:08:01"" updateDate=""2012-07-20T18:49:32"" nodeName=""Sub 2"" urlName=""sub-2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1175"" isDoc=""""><content><![CDATA[]]></content>
|
||||
</Home>
|
||||
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""4"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
|
||||
<CustomDocument id=""4444"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1234"" template=""" + templateId + @""" sortOrder=""3"" createDate=""2012-07-16T15:26:59"" updateDate=""2012-07-18T14:23:35"" nodeName=""Test"" urlName=""test-page"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,4444"" isDoc="""">
|
||||
<selectedNodes><![CDATA[1172,1176,1173]]></selectedNodes>
|
||||
</CustomDocument>
|
||||
</Home>
|
||||
@@ -62,38 +64,12 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
|
||||
new[]
|
||||
{
|
||||
typeof(DatePickerPropertyEditorValueConverter),
|
||||
typeof(TinyMcePropertyEditorValueConverter),
|
||||
typeof(YesNoPropertyEditorValueConverter)
|
||||
});
|
||||
|
||||
//need to specify a custom callback for unit tests
|
||||
DynamicPublishedContent.GetDataTypeCallback = (docTypeAlias, propertyAlias) =>
|
||||
{
|
||||
if (propertyAlias == "content")
|
||||
{
|
||||
//return the rte type id
|
||||
return Guid.Parse("5e9b75ae-face-41c8-b47e-5f4b0fd82f83");
|
||||
}
|
||||
return Guid.Empty;
|
||||
};
|
||||
|
||||
var umbCtx = GetUmbracoContext("/test", 1234);
|
||||
UmbracoContext.Current = umbCtx;
|
||||
PublishedContentStoreResolver.Current = new PublishedContentStoreResolver(new DefaultPublishedContentStore());
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
PropertyEditorValueConvertersResolver.Reset();
|
||||
PublishedContentStoreResolver.Reset();
|
||||
UmbracoContext.Current = null;
|
||||
|
||||
}
|
||||
|
||||
internal IPublishedContent GetNode(int id)
|
||||
@@ -105,6 +81,136 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
return doc;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Last_From_Where_Filter_Dynamic_Linq()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
foreach (var d in doc.Children.Where("Visible"))
|
||||
{
|
||||
if (d.Id != 1178)
|
||||
{
|
||||
Assert.IsFalse(d.IsLast());
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(d.IsLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Last_From_Where_Filter()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
foreach (var d in doc.Children.Where(x => x.IsVisible()))
|
||||
{
|
||||
if (d.Id != 1178)
|
||||
{
|
||||
Assert.IsFalse(d.IsLast());
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(d.IsLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Last_From_Take()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
foreach (var d in doc.Children.Take(3))
|
||||
{
|
||||
if (d.Id != 1178)
|
||||
{
|
||||
Assert.IsFalse(d.IsLast());
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(d.IsLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Last_From_Skip()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
foreach (var d in doc.Children.Skip(1))
|
||||
{
|
||||
if (d.Id != 1176)
|
||||
{
|
||||
Assert.IsFalse(d.IsLast());
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(d.IsLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Last_From_Concat()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
|
||||
foreach (var d in doc.Children.Concat(new[] { GetNode(1175), GetNode(4444) }))
|
||||
{
|
||||
if (d.Id != 4444)
|
||||
{
|
||||
Assert.IsFalse(d.IsLast());
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(d.IsLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants_Ordered_Properly()
|
||||
{
|
||||
var doc = GetNode(1046);
|
||||
|
||||
var currentLevel = 0;
|
||||
var lastSortOrder = 0;
|
||||
var levelChangesAt = new[] { 1046, 1173, 1174 };
|
||||
|
||||
foreach (var d in doc.DescendantsOrSelf())
|
||||
{
|
||||
if (levelChangesAt.Contains(d.Id))
|
||||
{
|
||||
Assert.Greater(d.Level, currentLevel);
|
||||
currentLevel = d.Level;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreEqual(currentLevel, d.Level);
|
||||
Assert.Greater(d.SortOrder, lastSortOrder);
|
||||
}
|
||||
lastSortOrder = d.SortOrder;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Property_Value_Uses_Converter()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
var propVal = doc.GetPropertyValue("content");
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal.GetType()));
|
||||
Assert.AreEqual("<div>This is some content</div>", propVal.ToString());
|
||||
|
||||
var propVal2 = doc.GetPropertyValue<IHtmlString>("content");
|
||||
Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(propVal2.GetType()));
|
||||
Assert.AreEqual("<div>This is some content</div>", propVal2.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Complex_Linq()
|
||||
{
|
||||
@@ -113,7 +219,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
var result = doc.Ancestors().OrderBy(x => x.Level)
|
||||
.Single()
|
||||
.Descendants()
|
||||
.FirstOrDefault(x => x.GetPropertyValue("selectedNodes", "").Split(',').Contains("1173"));
|
||||
.FirstOrDefault(x => x.GetPropertyValue<string>("selectedNodes", "").Split(',').Contains("1173"));
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
}
|
||||
@@ -124,11 +230,11 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
var doc = GetNode(1173);
|
||||
Assert.AreEqual(0, doc.Index());
|
||||
doc = GetNode(1176);
|
||||
Assert.AreEqual(1, doc.Index());
|
||||
doc = GetNode(1177);
|
||||
Assert.AreEqual(2, doc.Index());
|
||||
doc = GetNode(1178);
|
||||
Assert.AreEqual(3, doc.Index());
|
||||
doc = GetNode(1177);
|
||||
Assert.AreEqual(1, doc.Index());
|
||||
doc = GetNode(1178);
|
||||
Assert.AreEqual(2, doc.Index());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -255,17 +361,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
Assert.IsTrue(visible.IsVisible());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_TinyMCE_Converted_Type_User_Property()
|
||||
{
|
||||
var doc = GetNode(1173);
|
||||
|
||||
throw new NotImplementedException("We currently don't have an extension method to return the formatted value using IPropertyValueConverter! This currently only works in the dynamic implementation");
|
||||
|
||||
//Assert.IsTrue(TypeHelper.IsTypeAssignableFrom<IHtmlString>(doc.GetPropertyValue().Content.GetType()));
|
||||
//Assert.AreEqual("<div>This is some content</div>", doc.Content.ToString());
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Ancestor_Or_Self()
|
||||
{
|
||||
@@ -326,8 +422,8 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual(6, result.Count());
|
||||
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175 }));
|
||||
Assert.AreEqual(7, result.Count());
|
||||
Assert.IsTrue(result.Select(x => ((dynamic)x).Id).ContainsAll(new dynamic[] { 1173, 1174, 1176, 1175, 4444 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -369,7 +465,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
[Test]
|
||||
public void Next_Without_Sibling()
|
||||
{
|
||||
var doc = GetNode(1178);
|
||||
var doc = GetNode(1176);
|
||||
|
||||
Assert.IsNull(doc.Next());
|
||||
}
|
||||
@@ -391,7 +487,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual((int)1174, (int)result.Id);
|
||||
Assert.AreEqual((int)1178, (int)result.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Examine;
|
||||
using Examine.LuceneEngine;
|
||||
using Examine.LuceneEngine.Providers;
|
||||
using Lucene.Net.Analysis.Standard;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.ExamineHelpers;
|
||||
using Umbraco.Web;
|
||||
using UmbracoExamine;
|
||||
using UmbracoExamine.DataServices;
|
||||
using umbraco.BusinessLogic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the typed extension methods on IPublishedContent using the DefaultPublishedMediaStore
|
||||
/// </summary>
|
||||
[TestFixture, RequiresSTA]
|
||||
public class PublishedMediaTests : PublishedContentTestBase
|
||||
{
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
UmbracoSettings.ForceSafeAliases = true;
|
||||
UmbracoSettings.UmbracoLibraryCacheDuration = 1800;
|
||||
UmbracoSettings.ForceSafeAliases = true;
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shared with PublishMediaStoreTests
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <returns></returns>
|
||||
internal static IPublishedContent GetNode(int id, UmbracoContext umbracoContext)
|
||||
{
|
||||
var ctx = umbracoContext;
|
||||
var mediaStore = new DefaultPublishedMediaStore();
|
||||
var doc = mediaStore.GetDocumentById(ctx, id);
|
||||
Assert.IsNotNull(doc);
|
||||
return doc;
|
||||
}
|
||||
|
||||
private IPublishedContent GetNode(int id)
|
||||
{
|
||||
return GetNode(id, GetUmbracoContext("/test", 1234));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Children_Sorted_With_Examine()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var store = new DefaultPublishedMediaStore(
|
||||
indexInit.GetUmbracoSearcher(newIndexFolder),
|
||||
indexInit.GetUmbracoIndexer(newIndexFolder));
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
|
||||
var rootChildren = publishedMedia.Children().ToArray();
|
||||
var currSort = 0;
|
||||
for (var i = 0; i < rootChildren.Count(); i++)
|
||||
{
|
||||
Assert.GreaterOrEqual(rootChildren[i].SortOrder, currSort);
|
||||
currSort = rootChildren[i].SortOrder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_With_Examine()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var store = new DefaultPublishedMediaStore(
|
||||
indexInit.GetUmbracoSearcher(newIndexFolder),
|
||||
indexInit.GetUmbracoIndexer(newIndexFolder));
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
|
||||
var rootChildren = publishedMedia.Children();
|
||||
Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] { 2222, 1113, 1114, 1115, 1116 }));
|
||||
|
||||
var publishedChild1 = store.GetDocumentById(GetUmbracoContext("/test", 1234), 2222);
|
||||
var subChildren = publishedChild1.Children();
|
||||
Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { 2112 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants_With_Examine()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var store = new DefaultPublishedMediaStore(
|
||||
indexInit.GetUmbracoSearcher(newIndexFolder),
|
||||
indexInit.GetUmbracoIndexer(newIndexFolder));
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
|
||||
var rootDescendants = publishedMedia.Descendants();
|
||||
Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1113, 1114, 1115, 1116 }));
|
||||
|
||||
var publishedChild1 = store.GetDocumentById(GetUmbracoContext("/test", 1234), 2222);
|
||||
var subDescendants = publishedChild1.Descendants();
|
||||
Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2112, 3113 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DescendantsOrSelf_With_Examine()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var store = new DefaultPublishedMediaStore(
|
||||
indexInit.GetUmbracoSearcher(newIndexFolder),
|
||||
indexInit.GetUmbracoIndexer(newIndexFolder));
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 1111);
|
||||
var rootDescendants = publishedMedia.DescendantsOrSelf();
|
||||
Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { 1111, 2112, 2222, 1113, 1114, 1115, 1116 }));
|
||||
|
||||
var publishedChild1 = store.GetDocumentById(GetUmbracoContext("/test", 1234), 2222);
|
||||
var subDescendants = publishedChild1.DescendantsOrSelf();
|
||||
Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { 2222, 2112, 3113 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors_With_Examine()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var store = new DefaultPublishedMediaStore(
|
||||
indexInit.GetUmbracoSearcher(newIndexFolder),
|
||||
indexInit.GetUmbracoIndexer(newIndexFolder));
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 3113);
|
||||
var ancestors = publishedMedia.Ancestors();
|
||||
Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 2112, 2222, 1111 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AncestorsOrSelf_With_Examine()
|
||||
{
|
||||
var newIndexFolder = new DirectoryInfo(Path.Combine("App_Data\\CWSIndexSetTest", Guid.NewGuid().ToString()));
|
||||
var indexInit = new IndexInitializer();
|
||||
var indexer = indexInit.GetUmbracoIndexer(newIndexFolder);
|
||||
indexer.RebuildIndex();
|
||||
|
||||
var store = new DefaultPublishedMediaStore(
|
||||
indexInit.GetUmbracoSearcher(newIndexFolder),
|
||||
indexInit.GetUmbracoIndexer(newIndexFolder));
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = store.GetDocumentById(GetUmbracoContext("/test", 1234), 3113);
|
||||
var ancestors = publishedMedia.AncestorsOrSelf();
|
||||
Assert.IsTrue(ancestors.Select(x => x.Id).ContainsAll(new[] { 3113, 2112, 2222, 1111 }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Children_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
|
||||
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
|
||||
|
||||
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
|
||||
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
|
||||
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
|
||||
|
||||
var publishedMedia = GetNode(mRoot.Id);
|
||||
var rootChildren = publishedMedia.Children();
|
||||
Assert.IsTrue(rootChildren.Select(x => x.Id).ContainsAll(new[] {mChild1.Id, mChild2.Id, mChild3.Id}));
|
||||
|
||||
var publishedChild1 = GetNode(mChild1.Id);
|
||||
var subChildren = publishedChild1.Children();
|
||||
Assert.IsTrue(subChildren.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Descendants_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
|
||||
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
|
||||
|
||||
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
|
||||
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
|
||||
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
|
||||
|
||||
var publishedMedia = GetNode(mRoot.Id);
|
||||
var rootDescendants = publishedMedia.Descendants();
|
||||
Assert.IsTrue(rootDescendants.Select(x => x.Id).ContainsAll(new[] { mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
|
||||
|
||||
var publishedChild1 = GetNode(mChild1.Id);
|
||||
var subDescendants = publishedChild1.Descendants();
|
||||
Assert.IsTrue(subDescendants.Select(x => x.Id).ContainsAll(new[] { mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DescendantsOrSelf_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
|
||||
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
|
||||
|
||||
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
|
||||
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
|
||||
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
|
||||
|
||||
var publishedMedia = GetNode(mRoot.Id);
|
||||
var rootDescendantsOrSelf = publishedMedia.DescendantsOrSelf();
|
||||
Assert.IsTrue(rootDescendantsOrSelf.Select(x => x.Id).ContainsAll(
|
||||
new[] { mRoot.Id, mChild1.Id, mChild2.Id, mChild3.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
|
||||
|
||||
var publishedChild1 = GetNode(mChild1.Id);
|
||||
var subDescendantsOrSelf = publishedChild1.DescendantsOrSelf();
|
||||
Assert.IsTrue(subDescendantsOrSelf.Select(x => x.Id).ContainsAll(
|
||||
new[] { mChild1.Id, mSubChild1.Id, mSubChild2.Id, mSubChild3.Id }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parent_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
|
||||
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
|
||||
|
||||
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
|
||||
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
|
||||
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
|
||||
|
||||
var publishedRoot = GetNode(mRoot.Id);
|
||||
Assert.AreEqual(null, publishedRoot.Parent);
|
||||
|
||||
var publishedChild1 = GetNode(mChild1.Id);
|
||||
Assert.AreEqual(mRoot.Id, publishedChild1.Parent.Id);
|
||||
|
||||
var publishedSubChild1 = GetNode(mSubChild1.Id);
|
||||
Assert.AreEqual(mChild1.Id, publishedSubChild1.Parent.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ancestors_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
|
||||
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
|
||||
|
||||
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
|
||||
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
|
||||
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
|
||||
|
||||
var publishedSubChild1 = GetNode(mSubChild1.Id);
|
||||
Assert.IsTrue(publishedSubChild1.Ancestors().Select(x => x.Id).ContainsAll(new[] {mChild1.Id, mRoot.Id}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AncestorsOrSelf_Without_Examine()
|
||||
{
|
||||
var user = new User(0);
|
||||
var mType = global::umbraco.cms.businesslogic.media.MediaType.MakeNew(user, "TestMediaType");
|
||||
var mRoot = global::umbraco.cms.businesslogic.media.Media.MakeNew("MediaRoot", mType, user, -1);
|
||||
|
||||
var mChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child1", mType, user, mRoot.Id);
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot.Id);
|
||||
var mChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child3", mType, user, mRoot.Id);
|
||||
|
||||
var mSubChild1 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild1", mType, user, mChild1.Id);
|
||||
var mSubChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild2", mType, user, mChild1.Id);
|
||||
var mSubChild3 = global::umbraco.cms.businesslogic.media.Media.MakeNew("SubChild3", mType, user, mChild1.Id);
|
||||
|
||||
var publishedSubChild1 = GetNode(mSubChild1.Id);
|
||||
Assert.IsTrue(publishedSubChild1.AncestorsOrSelf().Select(x => x.Id).ContainsAll(
|
||||
new[] { mSubChild1.Id, mChild1.Id, mRoot.Id }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+58
-5
@@ -1,19 +1,30 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Tests.DynamicDocument
|
||||
namespace Umbraco.Tests.PublishedContent
|
||||
{
|
||||
[TestFixture]
|
||||
public class StronglyTypedQueryTests : BaseWebTest
|
||||
public class StronglyTypedQueryTests : PublishedContentTestBase
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
protected override bool RequiresDbSetup
|
||||
{
|
||||
get { return false; }
|
||||
@@ -69,7 +80,8 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
Assert.IsNotNull(doc);
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void Type_Test()
|
||||
{
|
||||
@@ -79,6 +91,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
Assert.AreEqual("John Smith", result[1].ArticleAuthor);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void As_Test()
|
||||
{
|
||||
@@ -203,7 +216,7 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
}
|
||||
}
|
||||
|
||||
public class PublishedContentWrapper : IPublishedContent
|
||||
public class PublishedContentWrapper : IPublishedContent, IOwnerCollectionAware<IPublishedContent>
|
||||
{
|
||||
protected IPublishedContent WrappedContent { get; private set; }
|
||||
|
||||
@@ -293,6 +306,46 @@ namespace Umbraco.Tests.DynamicDocument
|
||||
{
|
||||
return WrappedContent.GetProperty(alias);
|
||||
}
|
||||
|
||||
private IEnumerable<IPublishedContent> _ownersCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Need to get/set the owner collection when an item is returned from the result set of a query
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Based on this issue here: http://issues.umbraco.org/issue/U4-1797
|
||||
/// </remarks>
|
||||
IEnumerable<IPublishedContent> IOwnerCollectionAware<IPublishedContent>.OwnersCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
var publishedContentBase = WrappedContent as IOwnerCollectionAware<IPublishedContent>;
|
||||
if (publishedContentBase != null)
|
||||
{
|
||||
return publishedContentBase.OwnersCollection;
|
||||
}
|
||||
|
||||
//if the owners collection is null, we'll default to it's siblings
|
||||
if (_ownersCollection == null)
|
||||
{
|
||||
//get the root docs if parent is null
|
||||
_ownersCollection = this.Siblings();
|
||||
}
|
||||
return _ownersCollection;
|
||||
}
|
||||
set
|
||||
{
|
||||
var publishedContentBase = WrappedContent as IOwnerCollectionAware<IPublishedContent>;
|
||||
if (publishedContentBase != null)
|
||||
{
|
||||
publishedContentBase.OwnersCollection = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ownersCollection = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class HomeContentItem : ContentPageContentItem
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Resolvers
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Resolvers
|
||||
};
|
||||
|
||||
ActionsResolver.Current = new ActionsResolver(
|
||||
PluginManager.Current.ResolveActions());
|
||||
() => PluginManager.Current.ResolveActions());
|
||||
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
|
||||
namespace Umbraco.Tests.Resolvers
|
||||
{
|
||||
[TestFixture]
|
||||
public class LazyManyObjectResolverTests
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Resolution.IsFrozen = false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Lazy_Type_Resolution()
|
||||
{
|
||||
var resolver = new LazyResolver(new[] {new Lazy<Type>(() => typeof (TransientObject3))});
|
||||
resolver.AddType<TransientObject1>();
|
||||
resolver.AddType(new Lazy<Type>(() => typeof(TransientObject2)));
|
||||
|
||||
Resolution.Freeze();
|
||||
|
||||
Assert.IsFalse(resolver.HasResolvedTypes);
|
||||
|
||||
var instances1 = resolver.Objects;
|
||||
|
||||
Assert.IsTrue(resolver.HasResolvedTypes);
|
||||
|
||||
Assert.AreEqual(3, instances1.Count());
|
||||
Assert.IsTrue(instances1.Select(x => x.GetType()).ContainsAll(new []{typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3)}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Type_List_Delegates_Combination()
|
||||
{
|
||||
Func<IEnumerable<Type>> types = () => new[] { typeof(TransientObject3), typeof(TransientObject2) };
|
||||
|
||||
var resolver = new LazyResolver(types);
|
||||
resolver.AddTypeListDelegate(() => new[] { typeof(TransientObject1)});
|
||||
|
||||
Resolution.Freeze();
|
||||
|
||||
var instances1 = resolver.Objects;
|
||||
|
||||
Assert.AreEqual(3, instances1.Count());
|
||||
Assert.IsTrue(instances1.Select(x => x.GetType()).ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Type_List_Delegates_And_Lazy_Type_Combination()
|
||||
{
|
||||
Func<IEnumerable<Type>> types = () => new[] { typeof(TransientObject3) };
|
||||
|
||||
var resolver = new LazyResolver(types);
|
||||
resolver.AddType(new Lazy<Type>(() => typeof(TransientObject2)));
|
||||
resolver.AddType<TransientObject1>();
|
||||
|
||||
Resolution.Freeze();
|
||||
|
||||
var instances1 = resolver.Objects;
|
||||
|
||||
Assert.AreEqual(3, instances1.Count());
|
||||
Assert.IsTrue(instances1.Select(x => x.GetType()).ContainsAll(new[] { typeof(TransientObject1), typeof(TransientObject2), typeof(TransientObject3) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Throws_If_Duplication()
|
||||
{
|
||||
Func<IEnumerable<Type>> types = () => new[] { typeof(TransientObject3), typeof(TransientObject2), typeof(TransientObject1) };
|
||||
|
||||
var resolver = new LazyResolver(types);
|
||||
//duplicate, but will not throw here
|
||||
resolver.AddType<TransientObject1>();
|
||||
|
||||
Resolution.Freeze();
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var instances = resolver.Objects;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region Test classes
|
||||
|
||||
private interface ITestInterface
|
||||
{
|
||||
}
|
||||
|
||||
private class TransientObject1 : ITestInterface
|
||||
{
|
||||
}
|
||||
|
||||
private class TransientObject2 : ITestInterface
|
||||
{
|
||||
}
|
||||
|
||||
private class TransientObject3 : ITestInterface
|
||||
{
|
||||
}
|
||||
|
||||
private sealed class LazyResolver : LazyManyObjectsResolverBase<LazyResolver, ITestInterface>
|
||||
{
|
||||
public LazyResolver()
|
||||
: base(ObjectLifetimeScope.Transient)
|
||||
{
|
||||
}
|
||||
|
||||
public LazyResolver(IEnumerable<Lazy<Type>> values)
|
||||
:base (values, ObjectLifetimeScope.Transient)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public LazyResolver(Func<IEnumerable<Type>> typeList)
|
||||
: base(typeList, ObjectLifetimeScope.Transient)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable<ITestInterface> Objects
|
||||
{
|
||||
get { return Values; }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Resolvers
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager();
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Resolvers
|
||||
};
|
||||
|
||||
MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver(
|
||||
PluginManager.Current.ResolveMacroRenderings());
|
||||
() => PluginManager.Current.ResolveMacroRenderings());
|
||||
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user