Compare commits
96 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 25c68a5a36 | |||
| 82d433d291 | |||
| 69ae715998 | |||
| 1930022f19 | |||
| bece953fa3 | |||
| a41d37b1cf | |||
| 31603f7063 | |||
| 87ae16b89a | |||
| 4520c06454 | |||
| 9f0c00827d | |||
| 0df0b78b90 | |||
| c6b6685dc7 | |||
| 7c3c477f18 | |||
| d7cc626396 | |||
| 9d50a4d2a5 | |||
| 321e2f9de0 | |||
| 9834352de2 | |||
| 2341622243 | |||
| 956a51ab67 | |||
| e358d3b170 | |||
| 752ce55cfa | |||
| e6d6d3dd69 | |||
| dca14f3eb4 | |||
| 1abdca2432 | |||
| 6db4fedcad | |||
| 3e66235932 | |||
| 1ab321c7b1 | |||
| dffcf10032 | |||
| 054033c73f | |||
| 4fcd23d8dc | |||
| 209ccb9ae7 | |||
| 2850c8aa05 | |||
| 87a9a57e6d | |||
| f3f6504398 | |||
| c47d59a257 | |||
| d61d6008da | |||
| 403f64eeed | |||
| 5aa29cc150 | |||
| 9be3bdb8a5 | |||
| c0baac2b38 | |||
| b20fc22577 | |||
| 74ebf67aef | |||
| 33036f80fe | |||
| 0688550143 | |||
| d43b673092 | |||
| 4ec37b9d3a | |||
| 4eb0981552 | |||
| ed8cc2ad0d | |||
| 10bc7d0c1e | |||
| aa11d3504d | |||
| 6903ebda1f | |||
| 6c6e398c53 | |||
| bccb9655d0 | |||
| dd143681f1 | |||
| b1d4a99510 | |||
| b8ea50d644 | |||
| 1eab26c0f6 | |||
| 0543c620eb | |||
| 646e5f173d | |||
| b5594517bd | |||
| 5501c9531b | |||
| 8824ab2b27 | |||
| b60e292d5f | |||
| e1dcf6b061 | |||
| 246dfba8ac | |||
| c0c7d21001 | |||
| 7d189a6fb8 | |||
| e60dcfa144 | |||
| 3f8b779ae4 | |||
| 72dc5fc477 | |||
| 737f2fb707 | |||
| a13ead0d10 | |||
| 414dbe45a6 | |||
| 340328aeba | |||
| f875dc15f7 | |||
| 71242430da | |||
| 1e04735826 | |||
| b975a02bfa | |||
| 88ec514630 | |||
| 6f7ec84f18 | |||
| 4ee4f296fc | |||
| b9e4950e36 | |||
| ba52f9235e | |||
| 33ccf490ab | |||
| 101e116baf | |||
| ebf24d69b5 | |||
| c94662e49c | |||
| 5d37eaf993 | |||
| 1ded2c9baf | |||
| 2daacd8d57 | |||
| 3f4fa8b8ed | |||
| 03ba8c9e14 | |||
| 13b57c7638 | |||
| a8b297903d | |||
| 89b5774106 | |||
| 774f201514 |
@@ -110,3 +110,4 @@ src/Umbraco.Web.UI/umbraco/js/init.js
|
||||
build/ApiDocs/*
|
||||
build/ApiDocs/Output/*
|
||||
src/Umbraco.Web.UI.Client/bower_components/*
|
||||
src/umbraco.sln.ide
|
||||
|
||||
+29
-16
@@ -2,9 +2,18 @@
|
||||
IF NOT EXIST UmbracoVersion.txt (
|
||||
ECHO UmbracoVersion.txt missing!
|
||||
GOTO :showerror
|
||||
)
|
||||
SET /p release=<UmbracoVersion.txt
|
||||
SET comment=
|
||||
)
|
||||
|
||||
REM Get the version and comment from UmbracoVersion.txt lines 2 and 3
|
||||
SET "release="
|
||||
SET "comment="
|
||||
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
|
||||
FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED comment SET "comment=%%i"
|
||||
|
||||
REM If there's arguments on the command line overrule UmbracoVersion.txt and use that as the version
|
||||
IF [%1] NEQ [] (SET release=%1)
|
||||
IF [%2] NEQ [] (SET comment=%2) ELSE (IF [%1] NEQ [] (SET "comment="))
|
||||
|
||||
SET version=%release%
|
||||
|
||||
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
|
||||
@@ -14,8 +23,11 @@ ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %rel
|
||||
|
||||
ECHO Installing the Microsoft.Bcl.Build package before anything else, otherwise you'd have to run build.cmd twice
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
..\src\.nuget\NuGet.exe sources Remove -Name MyGetUmbracoCore
|
||||
..\src\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder%
|
||||
..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder%
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder%
|
||||
|
||||
ECHO Removing the belle build folder to make sure everything is clean as a whistle
|
||||
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
|
||||
@@ -30,21 +42,22 @@ ECHO Performing MSBuild and producing Umbraco binaries zip files
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
|
||||
ECHO Adding dummy files to include in the NuGet package so that empty folders actually get created
|
||||
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\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\Views\Partials\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\Views\MacroPartials\dummy.txt
|
||||
SET dummytext=This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete.
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\App_Code\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\App_Data\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\App_Plugins\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\css\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\masterpages\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\media\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\scripts\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\usercontrols\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\Views\Partials\dummy.txt
|
||||
ECHO %dummytext% > .\_BuildOutput\WebApp\Views\MacroPartials\dummy.txt
|
||||
|
||||
ECHO Adding Web.config transform files to the NuGet package
|
||||
ren .\_BuildOutput\WebApp\MacroScripts\Web.config Web.config.transform
|
||||
ren .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
|
||||
ren .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
|
||||
REN .\_BuildOutput\WebApp\MacroScripts\Web.config Web.config.transform
|
||||
REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
|
||||
REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
|
||||
|
||||
ECHO Packing the NuGet release files
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
|
||||
|
||||
@@ -252,14 +252,11 @@
|
||||
</Target>
|
||||
|
||||
<!-- Unlike 2010, the VS2012 build targets file doesn't clean up the umbraco.presentation dir, do it manually -->
|
||||
<!-- Also, it places umbraco.XmlSerializers.dll in the root, even though it's also in the bin folder. Kill! -->
|
||||
<Target Name="CleanupPresentation" DependsOnTargets="CompileProjects">
|
||||
<ItemGroup>
|
||||
<PresentationFolderToDelete Include="$(WebAppFolder)umbraco.presentation" />
|
||||
<XmlSerializersDll Include="$(WebAppFolder)umbraco.XmlSerializers.dll" />
|
||||
</ItemGroup>
|
||||
<RemoveDir Directories="@(PresentationFolderToDelete)" />
|
||||
<Delete Files="@(XmlSerializersDll)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CompileProjects" DependsOnTargets="CompileExternalExamineProjects">
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
<dependency id="AutoMapper" version="[3.0.0, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.4, 7.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.57, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.9.5, 2.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.3.0, 4.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
@@ -66,7 +66,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.dll" target="lib\umbraco.providers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\umbraco.providers.xml" target="lib\umbraco.providers.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\umbraco.XmlSerializers.dll" target="lib\umbraco.XmlSerializers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
|
||||
@@ -10,7 +10,7 @@ if ($project) {
|
||||
New-Item -ItemType Directory -Force -Path $backupPath
|
||||
New-Item -ItemType Directory -Force -Path $copyLogsPath
|
||||
|
||||
# After backing up, remove all dlls from bin folder in case dll files are included in the VS project
|
||||
# After backing up, remove all umbraco dlls from bin folder in case dll files are included in the VS project
|
||||
# See: http://issues.umbraco.org/issue/U4-4930
|
||||
$umbracoBinFolder = Join-Path $projectDestinationPath "bin"
|
||||
if(Test-Path $umbracoBinFolder) {
|
||||
@@ -19,6 +19,58 @@ if ($project) {
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBinBackupPath
|
||||
|
||||
robocopy $umbracoBinFolder $umbracoBinBackupPath /e /LOG:$copyLogsPath\UmbracoBinBackup.log
|
||||
Remove-Item $umbracoBinFolder\*.dll -Force -Confirm:$false
|
||||
|
||||
# Delete files Umbraco brings in
|
||||
if(Test-Path $umbracoBinFolder\businesslogic.dll) { Remove-Item $umbracoBinFolder\businesslogic.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\cms.dll) { Remove-Item $umbracoBinFolder\cms.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\controls.dll) { Remove-Item $umbracoBinFolder\controls.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\interfaces.dll) { Remove-Item $umbracoBinFolder\interfaces.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\log4net.dll) { Remove-Item $umbracoBinFolder\log4net.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll) { Remove-Item $umbracoBinFolder\Microsoft.ApplicationBlocks.Data.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.Web.Helpers.dll) { Remove-Item $umbracoBinFolder\Microsoft.Web.Helpers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\SQLCE4Umbraco.dll) { Remove-Item $umbracoBinFolder\SQLCE4Umbraco.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll) { Remove-Item $umbracoBinFolder\System.Data.SqlServerCe.Entity.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\TidyNet.dll) { Remove-Item $umbracoBinFolder\TidyNet.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.dll) { Remove-Item $umbracoBinFolder\umbraco.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Umbraco.Core.dll) { Remove-Item $umbracoBinFolder\Umbraco.Core.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.DataLayer.dll) { Remove-Item $umbracoBinFolder\umbraco.DataLayer.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.editorControls.dll) { Remove-Item $umbracoBinFolder\umbraco.editorControls.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.MacroEngines.dll) { Remove-Item $umbracoBinFolder\umbraco.MacroEngines.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll) { Remove-Item $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll -Force -Confirm:$false }
|
||||
|
||||
# Delete files Umbraco depends upon
|
||||
$amd64Folder = Join-Path $projectDestinationPath "bin\amd64"
|
||||
if(Test-Path $amd64Folder) { Remove-Item $amd64Folder -Force -Recurse -Confirm:$false }
|
||||
$x86Folder = Join-Path $projectDestinationPath "bin\x86"
|
||||
if(Test-Path $x86Folder) { Remove-Item $x86Folder -Force -Recurse -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\AutoMapper.dll) { Remove-Item $umbracoBinFolder\AutoMapper.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\AutoMapper.Net4.dll) { Remove-Item $umbracoBinFolder\AutoMapper.Net4.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\ClientDependency.Core.dll) { Remove-Item $umbracoBinFolder\ClientDependency.Core.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\ClientDependency.Core.Mvc.dll) { Remove-Item $umbracoBinFolder\ClientDependency.Core.Mvc.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\CookComputing.XmlRpcV2.dll) { Remove-Item $umbracoBinFolder\CookComputing.XmlRpcV2.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Examine.dll) { Remove-Item $umbracoBinFolder\Examine.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\HtmlAgilityPack.dll) { Remove-Item $umbracoBinFolder\HtmlAgilityPack.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\ICSharpCode.SharpZipLib.dll) { Remove-Item $umbracoBinFolder\ICSharpCode.SharpZipLib.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\ImageProcessor.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\ImageProcessor.Web.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.Web.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Lucene.Net.dll) { Remove-Item $umbracoBinFolder\Lucene.Net.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.Web.Infrastructure.dll) { Remove-Item $umbracoBinFolder\Microsoft.Web.Infrastructure.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.Web.Mvc.FixedDisplayModes.dll) { Remove-Item $umbracoBinFolder\Microsoft.Web.Mvc.FixedDisplayModes.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\MiniProfiler.dll) { Remove-Item $umbracoBinFolder\MiniProfiler.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\MySql.Data.dll) { Remove-Item $umbracoBinFolder\MySql.Data.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Newtonsoft.Json.dll) { Remove-Item $umbracoBinFolder\Newtonsoft.Json.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Net.Http.Formatting.dll) { Remove-Item $umbracoBinFolder\System.Net.Http.Formatting.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Helpers.dll) { Remove-Item $umbracoBinFolder\System.Web.Helpers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Http.dll) { Remove-Item $umbracoBinFolder\System.Web.Http.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Http.WebHost.dll) { Remove-Item $umbracoBinFolder\System.Web.Http.WebHost.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Mvc.dll) { Remove-Item $umbracoBinFolder\System.Web.Mvc.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Razor.dll) { Remove-Item $umbracoBinFolder\System.Web.Razor.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.WebPages.dll) { Remove-Item $umbracoBinFolder\System.Web.WebPages.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.WebPages.Deployment.dll) { Remove-Item $umbracoBinFolder\System.Web.WebPages.Deployment.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.WebPages.Razor.dll) { Remove-Item $umbracoBinFolder\System.Web.WebPages.Razor.dll -Force -Confirm:$false }
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
7.1.5
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.1.9
|
||||
@@ -229,5 +229,15 @@ namespace SqlCE4Umbraco
|
||||
return new SqlCeDataReaderHelper(SqlCeApplicationBlock.ExecuteReader(ConnectionString, CommandType.Text,
|
||||
commandText, parameters));
|
||||
}
|
||||
|
||||
internal IRecordsReader ExecuteReader(string commandText)
|
||||
{
|
||||
return ExecuteReader(commandText, new SqlCEParameter(string.Empty, string.Empty));
|
||||
}
|
||||
|
||||
internal int ExecuteNonQuery(string commandText)
|
||||
{
|
||||
return ExecuteNonQuery(commandText, new SqlCEParameter(string.Empty, string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
private bool ShouldExecute(ApplicationContext applicationContext)
|
||||
{
|
||||
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
|
||||
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.CanConnect)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Core
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
|
||||
if (!applicationContext.DatabaseContext.CanConnect && ExecuteWhenDatabaseNotConfigured)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,5 +5,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
public interface IScheduledTasksSection : IUmbracoConfigurationSection
|
||||
{
|
||||
IEnumerable<IScheduledTask> Tasks { get; }
|
||||
|
||||
string BaseUrl { get; }
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
get { return Tasks; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("baseUrl", IsRequired = false, DefaultValue = null)]
|
||||
public string BaseUrl
|
||||
{
|
||||
get { return (string)base["baseUrl"]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.1.5");
|
||||
private static readonly Version Version = new Version("7.1.9");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Umbraco.Core
|
||||
{
|
||||
private readonly IDatabaseFactory _factory;
|
||||
private bool _configured;
|
||||
private bool _canConnect;
|
||||
private volatile bool _connectCheck = false;
|
||||
private readonly object _locker = new object();
|
||||
private string _connectionString;
|
||||
private string _providerName;
|
||||
private DatabaseSchemaResult _result;
|
||||
@@ -56,6 +59,32 @@ namespace Umbraco.Core
|
||||
get { return _configured; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the db can be connected to
|
||||
/// </summary>
|
||||
public bool CanConnect
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDatabaseConfigured == false) return false;
|
||||
|
||||
//double check lock so that it is only checked once and is fast
|
||||
if (_connectCheck == false)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_canConnect == false)
|
||||
{
|
||||
_canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
|
||||
_connectCheck = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _canConnect;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configured umbraco db connection string.
|
||||
/// </summary>
|
||||
|
||||
@@ -34,6 +34,12 @@ namespace Umbraco.Core
|
||||
AddInt(d.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCulture).GetHashCode(s));
|
||||
}
|
||||
|
||||
internal void AddCaseInsensitiveString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
|
||||
@@ -165,6 +165,16 @@ namespace Umbraco.Core.Media
|
||||
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
|
||||
|
||||
// Save the new image using the dimensions of the image
|
||||
var predictableThumbnailName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", maxWidthHeight.ToString(CultureInfo.InvariantCulture));
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
bp.Save(ms, codec, ep);
|
||||
ms.Seek(0, 0);
|
||||
|
||||
fs.AddFile(predictableThumbnailName, ms);
|
||||
}
|
||||
|
||||
// TODO: Remove this, this is ONLY here for backwards compatibility but it is essentially completely unusable see U4-5385
|
||||
var newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh));
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Umbraco.Core.Persistence
|
||||
connection.Open();
|
||||
connection.Close();
|
||||
}
|
||||
catch (SqlException)
|
||||
catch (DbException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Caching;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
@@ -1709,8 +1710,32 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
public override object ChangeType(object val) { return val; }
|
||||
}
|
||||
public class PocoData
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Container for a Memory cache object
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Better to have one memory cache instance than many so it's memory management can be handled more effectively
|
||||
/// http://stackoverflow.com/questions/8463962/using-multiple-instances-of-memorycache
|
||||
/// </remarks>
|
||||
internal class ManagedCache
|
||||
{
|
||||
public ObjectCache GetCache()
|
||||
{
|
||||
return ObjectCache;
|
||||
}
|
||||
|
||||
static readonly ObjectCache ObjectCache = new MemoryCache("NPoco");
|
||||
|
||||
}
|
||||
|
||||
public class PocoData
|
||||
{
|
||||
//USE ONLY FOR TESTING
|
||||
internal static bool UseLongKeys = false;
|
||||
//USE ONLY FOR TESTING - default is one hr
|
||||
internal static int SlidingExpirationSeconds = 3600;
|
||||
|
||||
public static PocoData ForObject(object o, string primaryKeyName)
|
||||
{
|
||||
var t = o.GetType();
|
||||
@@ -1734,7 +1759,7 @@ namespace Umbraco.Core.Persistence
|
||||
#endif
|
||||
return ForType(t);
|
||||
}
|
||||
static System.Threading.ReaderWriterLockSlim RWLock = new System.Threading.ReaderWriterLockSlim();
|
||||
|
||||
public static PocoData ForType(Type t)
|
||||
{
|
||||
#if !PETAPOCO_NO_DYNAMIC
|
||||
@@ -1742,7 +1767,7 @@ namespace Umbraco.Core.Persistence
|
||||
throw new InvalidOperationException("Can't use dynamic types with this method");
|
||||
#endif
|
||||
// Check cache
|
||||
RWLock.EnterReadLock();
|
||||
InnerLock.EnterReadLock();
|
||||
PocoData pd;
|
||||
try
|
||||
{
|
||||
@@ -1751,12 +1776,12 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
finally
|
||||
{
|
||||
RWLock.ExitReadLock();
|
||||
InnerLock.ExitReadLock();
|
||||
}
|
||||
|
||||
|
||||
// Cache it
|
||||
RWLock.EnterWriteLock();
|
||||
InnerLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
// Check again
|
||||
@@ -1770,7 +1795,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
finally
|
||||
{
|
||||
RWLock.ExitWriteLock();
|
||||
InnerLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
return pd;
|
||||
@@ -1851,224 +1876,237 @@ namespace Umbraco.Core.Persistence
|
||||
return tc >= TypeCode.SByte && tc <= TypeCode.UInt64;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create factory function that can convert a IDataReader record into a POCO
|
||||
public Delegate GetFactory(string sql, string connString, bool ForceDateTimesToUtc, int firstColumn, int countColumns, IDataReader r)
|
||||
{
|
||||
// Check cache
|
||||
var key = string.Format("{0}:{1}:{2}:{3}:{4}", sql, connString, ForceDateTimesToUtc, firstColumn, countColumns);
|
||||
RWLock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
// Have we already created it?
|
||||
Delegate factory;
|
||||
if (PocoFactories.TryGetValue(key, out factory))
|
||||
return factory;
|
||||
}
|
||||
finally
|
||||
{
|
||||
RWLock.ExitReadLock();
|
||||
}
|
||||
|
||||
// Take the writer lock
|
||||
RWLock.EnterWriteLock();
|
||||
//TODO: It would be nice to remove the irrelevant SQL parts - for a mapping operation anything after the SELECT clause isn't required.
|
||||
// This would ensure less duplicate entries that get cached, currently both of these queries would be cached even though they are
|
||||
// returning the same structured data:
|
||||
// SELECT * FROM MyTable ORDER BY MyColumn
|
||||
// SELECT * FROM MyTable ORDER BY MyColumn DESC
|
||||
|
||||
try
|
||||
{
|
||||
string key;
|
||||
if (UseLongKeys)
|
||||
{
|
||||
key = string.Format("{0}:{1}:{2}:{3}:{4}", sql, connString, ForceDateTimesToUtc, firstColumn, countColumns);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Create a hashed key, we don't want to store so much string data in memory
|
||||
var combiner = new HashCodeCombiner();
|
||||
combiner.AddCaseInsensitiveString(sql);
|
||||
combiner.AddCaseInsensitiveString(connString);
|
||||
combiner.AddObject(ForceDateTimesToUtc);
|
||||
combiner.AddInt(firstColumn);
|
||||
combiner.AddInt(countColumns);
|
||||
key = combiner.GetCombinedHashCode();
|
||||
}
|
||||
|
||||
|
||||
// Check again, just in case
|
||||
Delegate factory;
|
||||
if (PocoFactories.TryGetValue(key, out factory))
|
||||
return factory;
|
||||
var objectCache = _managedCache.GetCache();
|
||||
|
||||
// Create the method
|
||||
var m = new DynamicMethod("petapoco_factory_" + PocoFactories.Count.ToString(), type, new Type[] { typeof(IDataReader) }, true);
|
||||
var il = m.GetILGenerator();
|
||||
Func<Delegate> factory = () =>
|
||||
{
|
||||
// Create the method
|
||||
var m = new DynamicMethod("petapoco_factory_" + objectCache.GetCount(), type, new Type[] { typeof(IDataReader) }, true);
|
||||
var il = m.GetILGenerator();
|
||||
|
||||
#if !PETAPOCO_NO_DYNAMIC
|
||||
if (type == typeof(object))
|
||||
{
|
||||
// var poco=new T()
|
||||
il.Emit(OpCodes.Newobj, typeof(System.Dynamic.ExpandoObject).GetConstructor(Type.EmptyTypes)); // obj
|
||||
if (type == typeof(object))
|
||||
{
|
||||
// var poco=new T()
|
||||
il.Emit(OpCodes.Newobj, typeof(System.Dynamic.ExpandoObject).GetConstructor(Type.EmptyTypes)); // obj
|
||||
|
||||
MethodInfo fnAdd = typeof(IDictionary<string, object>).GetMethod("Add");
|
||||
MethodInfo fnAdd = typeof(IDictionary<string, object>).GetMethod("Add");
|
||||
|
||||
// Enumerate all fields generating a set assignment for the column
|
||||
for (int i = firstColumn; i < firstColumn + countColumns; i++)
|
||||
{
|
||||
var srcType = r.GetFieldType(i);
|
||||
// Enumerate all fields generating a set assignment for the column
|
||||
for (int i = firstColumn; i < firstColumn + countColumns; i++)
|
||||
{
|
||||
var srcType = r.GetFieldType(i);
|
||||
|
||||
il.Emit(OpCodes.Dup); // obj, obj
|
||||
il.Emit(OpCodes.Ldstr, r.GetName(i)); // obj, obj, fieldname
|
||||
il.Emit(OpCodes.Dup); // obj, obj
|
||||
il.Emit(OpCodes.Ldstr, r.GetName(i)); // obj, obj, fieldname
|
||||
|
||||
// Get the converter
|
||||
Func<object, object> converter = null;
|
||||
if (Database.Mapper != null)
|
||||
converter = Database.Mapper.GetFromDbConverter(null, srcType);
|
||||
if (ForceDateTimesToUtc && converter == null && srcType == typeof(DateTime))
|
||||
converter = delegate(object src) { return new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); };
|
||||
// Get the converter
|
||||
Func<object, object> converter = null;
|
||||
if (Database.Mapper != null)
|
||||
converter = Database.Mapper.GetFromDbConverter(null, srcType);
|
||||
if (ForceDateTimesToUtc && converter == null && srcType == typeof(DateTime))
|
||||
converter = delegate(object src) { return new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); };
|
||||
|
||||
// Setup stack for call to converter
|
||||
AddConverterToStack(il, converter);
|
||||
// Setup stack for call to converter
|
||||
AddConverterToStack(il, converter);
|
||||
|
||||
// r[i]
|
||||
il.Emit(OpCodes.Ldarg_0); // obj, obj, fieldname, converter?, rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // obj, obj, fieldname, converter?, rdr,i
|
||||
il.Emit(OpCodes.Callvirt, fnGetValue); // obj, obj, fieldname, converter?, value
|
||||
// r[i]
|
||||
il.Emit(OpCodes.Ldarg_0); // obj, obj, fieldname, converter?, rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // obj, obj, fieldname, converter?, rdr,i
|
||||
il.Emit(OpCodes.Callvirt, fnGetValue); // obj, obj, fieldname, converter?, value
|
||||
|
||||
// Convert DBNull to null
|
||||
il.Emit(OpCodes.Dup); // obj, obj, fieldname, converter?, value, value
|
||||
il.Emit(OpCodes.Isinst, typeof(DBNull)); // obj, obj, fieldname, converter?, value, (value or null)
|
||||
var lblNotNull = il.DefineLabel();
|
||||
il.Emit(OpCodes.Brfalse_S, lblNotNull); // obj, obj, fieldname, converter?, value
|
||||
il.Emit(OpCodes.Pop); // obj, obj, fieldname, converter?
|
||||
if (converter != null)
|
||||
il.Emit(OpCodes.Pop); // obj, obj, fieldname,
|
||||
il.Emit(OpCodes.Ldnull); // obj, obj, fieldname, null
|
||||
if (converter != null)
|
||||
{
|
||||
var lblReady = il.DefineLabel();
|
||||
il.Emit(OpCodes.Br_S, lblReady);
|
||||
il.MarkLabel(lblNotNull);
|
||||
il.Emit(OpCodes.Callvirt, fnInvoke);
|
||||
il.MarkLabel(lblReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.MarkLabel(lblNotNull);
|
||||
}
|
||||
// Convert DBNull to null
|
||||
il.Emit(OpCodes.Dup); // obj, obj, fieldname, converter?, value, value
|
||||
il.Emit(OpCodes.Isinst, typeof(DBNull)); // obj, obj, fieldname, converter?, value, (value or null)
|
||||
var lblNotNull = il.DefineLabel();
|
||||
il.Emit(OpCodes.Brfalse_S, lblNotNull); // obj, obj, fieldname, converter?, value
|
||||
il.Emit(OpCodes.Pop); // obj, obj, fieldname, converter?
|
||||
if (converter != null)
|
||||
il.Emit(OpCodes.Pop); // obj, obj, fieldname,
|
||||
il.Emit(OpCodes.Ldnull); // obj, obj, fieldname, null
|
||||
if (converter != null)
|
||||
{
|
||||
var lblReady = il.DefineLabel();
|
||||
il.Emit(OpCodes.Br_S, lblReady);
|
||||
il.MarkLabel(lblNotNull);
|
||||
il.Emit(OpCodes.Callvirt, fnInvoke);
|
||||
il.MarkLabel(lblReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.MarkLabel(lblNotNull);
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Callvirt, fnAdd);
|
||||
}
|
||||
}
|
||||
else
|
||||
il.Emit(OpCodes.Callvirt, fnAdd);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (type.IsValueType || type == typeof(string) || type == typeof(byte[]))
|
||||
{
|
||||
// Do we need to install a converter?
|
||||
var srcType = r.GetFieldType(0);
|
||||
var converter = GetConverter(ForceDateTimesToUtc, null, srcType, type);
|
||||
if (type.IsValueType || type == typeof(string) || type == typeof(byte[]))
|
||||
{
|
||||
// Do we need to install a converter?
|
||||
var srcType = r.GetFieldType(0);
|
||||
var converter = GetConverter(ForceDateTimesToUtc, null, srcType, type);
|
||||
|
||||
// "if (!rdr.IsDBNull(i))"
|
||||
il.Emit(OpCodes.Ldarg_0); // rdr
|
||||
il.Emit(OpCodes.Ldc_I4_0); // rdr,0
|
||||
il.Emit(OpCodes.Callvirt, fnIsDBNull); // bool
|
||||
var lblCont = il.DefineLabel();
|
||||
il.Emit(OpCodes.Brfalse_S, lblCont);
|
||||
il.Emit(OpCodes.Ldnull); // null
|
||||
var lblFin = il.DefineLabel();
|
||||
il.Emit(OpCodes.Br_S, lblFin);
|
||||
// "if (!rdr.IsDBNull(i))"
|
||||
il.Emit(OpCodes.Ldarg_0); // rdr
|
||||
il.Emit(OpCodes.Ldc_I4_0); // rdr,0
|
||||
il.Emit(OpCodes.Callvirt, fnIsDBNull); // bool
|
||||
var lblCont = il.DefineLabel();
|
||||
il.Emit(OpCodes.Brfalse_S, lblCont);
|
||||
il.Emit(OpCodes.Ldnull); // null
|
||||
var lblFin = il.DefineLabel();
|
||||
il.Emit(OpCodes.Br_S, lblFin);
|
||||
|
||||
il.MarkLabel(lblCont);
|
||||
il.MarkLabel(lblCont);
|
||||
|
||||
// Setup stack for call to converter
|
||||
AddConverterToStack(il, converter);
|
||||
// Setup stack for call to converter
|
||||
AddConverterToStack(il, converter);
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0); // rdr
|
||||
il.Emit(OpCodes.Ldc_I4_0); // rdr,0
|
||||
il.Emit(OpCodes.Callvirt, fnGetValue); // value
|
||||
il.Emit(OpCodes.Ldarg_0); // rdr
|
||||
il.Emit(OpCodes.Ldc_I4_0); // rdr,0
|
||||
il.Emit(OpCodes.Callvirt, fnGetValue); // value
|
||||
|
||||
// Call the converter
|
||||
if (converter != null)
|
||||
il.Emit(OpCodes.Callvirt, fnInvoke);
|
||||
// Call the converter
|
||||
if (converter != null)
|
||||
il.Emit(OpCodes.Callvirt, fnInvoke);
|
||||
|
||||
il.MarkLabel(lblFin);
|
||||
il.Emit(OpCodes.Unbox_Any, type); // value converted
|
||||
}
|
||||
else
|
||||
{
|
||||
// var poco=new T()
|
||||
il.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null));
|
||||
il.MarkLabel(lblFin);
|
||||
il.Emit(OpCodes.Unbox_Any, type); // value converted
|
||||
}
|
||||
else
|
||||
{
|
||||
// var poco=new T()
|
||||
il.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null));
|
||||
|
||||
// Enumerate all fields generating a set assignment for the column
|
||||
for (int i = firstColumn; i < firstColumn + countColumns; i++)
|
||||
{
|
||||
// Get the PocoColumn for this db column, ignore if not known
|
||||
PocoColumn pc;
|
||||
if (!Columns.TryGetValue(r.GetName(i), out pc))
|
||||
continue;
|
||||
// Enumerate all fields generating a set assignment for the column
|
||||
for (int i = firstColumn; i < firstColumn + countColumns; i++)
|
||||
{
|
||||
// Get the PocoColumn for this db column, ignore if not known
|
||||
PocoColumn pc;
|
||||
if (!Columns.TryGetValue(r.GetName(i), out pc))
|
||||
continue;
|
||||
|
||||
// Get the source type for this column
|
||||
var srcType = r.GetFieldType(i);
|
||||
var dstType = pc.PropertyInfo.PropertyType;
|
||||
// Get the source type for this column
|
||||
var srcType = r.GetFieldType(i);
|
||||
var dstType = pc.PropertyInfo.PropertyType;
|
||||
|
||||
// "if (!rdr.IsDBNull(i))"
|
||||
il.Emit(OpCodes.Ldarg_0); // poco,rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // poco,rdr,i
|
||||
il.Emit(OpCodes.Callvirt, fnIsDBNull); // poco,bool
|
||||
var lblNext = il.DefineLabel();
|
||||
il.Emit(OpCodes.Brtrue_S, lblNext); // poco
|
||||
// "if (!rdr.IsDBNull(i))"
|
||||
il.Emit(OpCodes.Ldarg_0); // poco,rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // poco,rdr,i
|
||||
il.Emit(OpCodes.Callvirt, fnIsDBNull); // poco,bool
|
||||
var lblNext = il.DefineLabel();
|
||||
il.Emit(OpCodes.Brtrue_S, lblNext); // poco
|
||||
|
||||
il.Emit(OpCodes.Dup); // poco,poco
|
||||
il.Emit(OpCodes.Dup); // poco,poco
|
||||
|
||||
// Do we need to install a converter?
|
||||
var converter = GetConverter(ForceDateTimesToUtc, pc, srcType, dstType);
|
||||
// Do we need to install a converter?
|
||||
var converter = GetConverter(ForceDateTimesToUtc, pc, srcType, dstType);
|
||||
|
||||
// Fast
|
||||
bool Handled = false;
|
||||
if (converter == null)
|
||||
{
|
||||
var valuegetter = typeof(IDataRecord).GetMethod("Get" + srcType.Name, new Type[] { typeof(int) });
|
||||
if (valuegetter != null
|
||||
&& valuegetter.ReturnType == srcType
|
||||
&& (valuegetter.ReturnType == dstType || valuegetter.ReturnType == Nullable.GetUnderlyingType(dstType)))
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_0); // *,rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i
|
||||
il.Emit(OpCodes.Callvirt, valuegetter); // *,value
|
||||
// Fast
|
||||
bool Handled = false;
|
||||
if (converter == null)
|
||||
{
|
||||
var valuegetter = typeof(IDataRecord).GetMethod("Get" + srcType.Name, new Type[] { typeof(int) });
|
||||
if (valuegetter != null
|
||||
&& valuegetter.ReturnType == srcType
|
||||
&& (valuegetter.ReturnType == dstType || valuegetter.ReturnType == Nullable.GetUnderlyingType(dstType)))
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_0); // *,rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i
|
||||
il.Emit(OpCodes.Callvirt, valuegetter); // *,value
|
||||
|
||||
// Convert to Nullable
|
||||
if (Nullable.GetUnderlyingType(dstType) != null)
|
||||
{
|
||||
il.Emit(OpCodes.Newobj, dstType.GetConstructor(new Type[] { Nullable.GetUnderlyingType(dstType) }));
|
||||
}
|
||||
// Convert to Nullable
|
||||
if (Nullable.GetUnderlyingType(dstType) != null)
|
||||
{
|
||||
il.Emit(OpCodes.Newobj, dstType.GetConstructor(new Type[] { Nullable.GetUnderlyingType(dstType) }));
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco
|
||||
Handled = true;
|
||||
}
|
||||
}
|
||||
il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco
|
||||
Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Not so fast
|
||||
if (!Handled)
|
||||
{
|
||||
// Setup stack for call to converter
|
||||
AddConverterToStack(il, converter);
|
||||
// Not so fast
|
||||
if (!Handled)
|
||||
{
|
||||
// Setup stack for call to converter
|
||||
AddConverterToStack(il, converter);
|
||||
|
||||
// "value = rdr.GetValue(i)"
|
||||
il.Emit(OpCodes.Ldarg_0); // *,rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i
|
||||
il.Emit(OpCodes.Callvirt, fnGetValue); // *,value
|
||||
// "value = rdr.GetValue(i)"
|
||||
il.Emit(OpCodes.Ldarg_0); // *,rdr
|
||||
il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i
|
||||
il.Emit(OpCodes.Callvirt, fnGetValue); // *,value
|
||||
|
||||
// Call the converter
|
||||
if (converter != null)
|
||||
il.Emit(OpCodes.Callvirt, fnInvoke);
|
||||
// Call the converter
|
||||
if (converter != null)
|
||||
il.Emit(OpCodes.Callvirt, fnInvoke);
|
||||
|
||||
// Assign it
|
||||
il.Emit(OpCodes.Unbox_Any, pc.PropertyInfo.PropertyType); // poco,poco,value
|
||||
il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco
|
||||
}
|
||||
// Assign it
|
||||
il.Emit(OpCodes.Unbox_Any, pc.PropertyInfo.PropertyType); // poco,poco,value
|
||||
il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco
|
||||
}
|
||||
|
||||
il.MarkLabel(lblNext);
|
||||
}
|
||||
il.MarkLabel(lblNext);
|
||||
}
|
||||
|
||||
var fnOnLoaded = RecurseInheritedTypes<MethodInfo>(type, (x) => x.GetMethod("OnLoaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null));
|
||||
if (fnOnLoaded != null)
|
||||
{
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Callvirt, fnOnLoaded);
|
||||
}
|
||||
}
|
||||
var fnOnLoaded = RecurseInheritedTypes<MethodInfo>(type, (x) => x.GetMethod("OnLoaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null));
|
||||
if (fnOnLoaded != null)
|
||||
{
|
||||
il.Emit(OpCodes.Dup);
|
||||
il.Emit(OpCodes.Callvirt, fnOnLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
il.Emit(OpCodes.Ret);
|
||||
|
||||
// return it
|
||||
var del = m.CreateDelegate(Expression.GetFuncType(typeof(IDataReader), type));
|
||||
|
||||
return del;
|
||||
};
|
||||
|
||||
//lazy usage of AddOrGetExisting ref: http://stackoverflow.com/questions/10559279/how-to-deal-with-costly-building-operations-using-memorycache/15894928#15894928
|
||||
var newValue = new Lazy<Delegate>(factory);
|
||||
// the line belows returns existing item or adds the new value if it doesn't exist
|
||||
var value = (Lazy<Delegate>)objectCache.AddOrGetExisting(key, newValue, new CacheItemPolicy
|
||||
{
|
||||
//sliding expiration of 1 hr, if the same key isn't used in this
|
||||
// timeframe it will be removed from the cache
|
||||
SlidingExpiration = new TimeSpan(0, 0, SlidingExpirationSeconds)
|
||||
});
|
||||
return (value ?? newValue).Value; // Lazy<T> handles the locking itself
|
||||
|
||||
// Cache it, return it
|
||||
var del = m.CreateDelegate(Expression.GetFuncType(typeof(IDataReader), type));
|
||||
PocoFactories.Add(key, del);
|
||||
return del;
|
||||
}
|
||||
finally
|
||||
{
|
||||
RWLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddConverterToStack(ILGenerator il, Func<object, object> converter)
|
||||
@@ -2144,7 +2182,7 @@ namespace Umbraco.Core.Persistence
|
||||
return default(T);
|
||||
}
|
||||
|
||||
|
||||
ManagedCache _managedCache = new ManagedCache();
|
||||
static Dictionary<Type, PocoData> m_PocoDatas = new Dictionary<Type, PocoData>();
|
||||
static List<Func<object, object>> m_Converters = new List<Func<object, object>>();
|
||||
static MethodInfo fnGetValue = typeof(IDataRecord).GetMethod("GetValue", new Type[] { typeof(int) });
|
||||
@@ -2156,7 +2194,46 @@ namespace Umbraco.Core.Persistence
|
||||
public string[] QueryColumns { get; private set; }
|
||||
public TableInfo TableInfo { get; private set; }
|
||||
public Dictionary<string, PocoColumn> Columns { get; private set; }
|
||||
Dictionary<string, Delegate> PocoFactories = new Dictionary<string, Delegate>();
|
||||
static System.Threading.ReaderWriterLockSlim InnerLock = new System.Threading.ReaderWriterLockSlim();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a report of the current cache being utilized by PetaPoco
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string PrintDebugCacheReport(out double totalBytes, out IEnumerable<string> allKeys)
|
||||
{
|
||||
var managedCache = new ManagedCache();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("m_PocoDatas:");
|
||||
foreach (var pocoData in m_PocoDatas)
|
||||
{
|
||||
sb.AppendFormat("\t{0}\n", pocoData.Key);
|
||||
sb.AppendFormat("\t\tTable:{0} - Col count:{1}\n", pocoData.Value.TableInfo.TableName, pocoData.Value.QueryColumns.Length);
|
||||
}
|
||||
|
||||
var cache = managedCache.GetCache();
|
||||
allKeys = cache.Select(x => x.Key).ToArray();
|
||||
|
||||
sb.AppendFormat("\tTotal Poco data count:{0}\n", allKeys.Count());
|
||||
|
||||
var keys = string.Join("", cache.Select(x => x.Key));
|
||||
//Bytes in .Net are stored as utf-16 = unicode little endian
|
||||
totalBytes = Encoding.Unicode.GetByteCount(keys);
|
||||
|
||||
sb.AppendFormat("\tTotal byte for keys:{0}\n", totalBytes);
|
||||
|
||||
sb.AppendLine("\tAll Poco cache items:");
|
||||
|
||||
foreach (var item in cache)
|
||||
{
|
||||
sb.AppendFormat("\t\t Key -> {0}\n", item.Key);
|
||||
sb.AppendFormat("\t\t Value -> {0}\n", item.Value);
|
||||
}
|
||||
|
||||
sb.AppendLine("-------------------END REPORT------------------------");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence
|
||||
var expresionist = new PocoToSqlExpressionHelper<T>();
|
||||
string whereExpression = expresionist.Visit(predicate);
|
||||
|
||||
return sql.Where(whereExpression);
|
||||
return sql.Where(whereExpression, expresionist.GetSqlParameters());
|
||||
}
|
||||
|
||||
public static Sql OrderBy<TColumn>(this Sql sql, Expression<Func<TColumn, object>> columnMember)
|
||||
@@ -129,7 +129,7 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
public static Sql OrderByDescending(this Sql sql, params object[] columns)
|
||||
{
|
||||
return sql.Append(new Sql("ORDER BY " + String.Join(", ", (from x in columns select x.ToString() + " DESC").ToArray())));
|
||||
return sql.Append(new Sql("ORDER BY " + String.Join(", ", (from x in columns select x + " DESC").ToArray())));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,562 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
internal abstract class BaseExpressionHelper<T> : BaseExpressionHelper
|
||||
{
|
||||
protected abstract string VisitMemberAccess(MemberExpression m);
|
||||
|
||||
protected internal virtual string Visit(Expression exp)
|
||||
{
|
||||
|
||||
if (exp == null) return string.Empty;
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Lambda:
|
||||
return VisitLambda(exp as LambdaExpression);
|
||||
case ExpressionType.MemberAccess:
|
||||
return VisitMemberAccess(exp as MemberExpression);
|
||||
case ExpressionType.Constant:
|
||||
return VisitConstant(exp as ConstantExpression);
|
||||
case ExpressionType.Add:
|
||||
case ExpressionType.AddChecked:
|
||||
case ExpressionType.Subtract:
|
||||
case ExpressionType.SubtractChecked:
|
||||
case ExpressionType.Multiply:
|
||||
case ExpressionType.MultiplyChecked:
|
||||
case ExpressionType.Divide:
|
||||
case ExpressionType.Modulo:
|
||||
case ExpressionType.And:
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.Or:
|
||||
case ExpressionType.OrElse:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.Coalesce:
|
||||
case ExpressionType.ArrayIndex:
|
||||
case ExpressionType.RightShift:
|
||||
case ExpressionType.LeftShift:
|
||||
case ExpressionType.ExclusiveOr:
|
||||
return VisitBinary(exp as BinaryExpression);
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
case ExpressionType.Not:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
case ExpressionType.ArrayLength:
|
||||
case ExpressionType.Quote:
|
||||
case ExpressionType.TypeAs:
|
||||
return VisitUnary(exp as UnaryExpression);
|
||||
case ExpressionType.Parameter:
|
||||
return VisitParameter(exp as ParameterExpression);
|
||||
case ExpressionType.Call:
|
||||
return VisitMethodCall(exp as MethodCallExpression);
|
||||
case ExpressionType.New:
|
||||
return VisitNew(exp as NewExpression);
|
||||
case ExpressionType.NewArrayInit:
|
||||
case ExpressionType.NewArrayBounds:
|
||||
return VisitNewArray(exp as NewArrayExpression);
|
||||
default:
|
||||
return exp.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitLambda(LambdaExpression lambda)
|
||||
{
|
||||
if (lambda.Body.NodeType == ExpressionType.MemberAccess)
|
||||
{
|
||||
var m = lambda.Body as MemberExpression;
|
||||
|
||||
if (m.Expression != null)
|
||||
{
|
||||
//This deals with members that are boolean (i.e. x => IsTrashed )
|
||||
string r = VisitMemberAccess(m);
|
||||
SqlParameters.Add(true);
|
||||
return string.Format("{0} = @{1}", r, SqlParameters.Count - 1);
|
||||
|
||||
//return string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
|
||||
}
|
||||
return Visit(lambda.Body);
|
||||
}
|
||||
|
||||
protected virtual string VisitBinary(BinaryExpression b)
|
||||
{
|
||||
string left, right;
|
||||
var operand = BindOperant(b.NodeType);
|
||||
if (operand == "AND" || operand == "OR")
|
||||
{
|
||||
MemberExpression m = b.Left as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
|
||||
SqlParameters.Add(1);
|
||||
left = string.Format("{0} = @{1}", r, SqlParameters.Count - 1);
|
||||
|
||||
//left = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
}
|
||||
m = b.Right as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
|
||||
SqlParameters.Add(1);
|
||||
right = string.Format("{0} = @{1}", r, SqlParameters.Count - 1);
|
||||
|
||||
//right = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
|
||||
if (operand == "=" && right == "null") operand = "is";
|
||||
else if (operand == "<>" && right == "null") operand = "is not";
|
||||
else if (operand == "=" || operand == "<>")
|
||||
{
|
||||
//if (IsTrueExpression(right)) right = GetQuotedTrueValue();
|
||||
//else if (IsFalseExpression(right)) right = GetQuotedFalseValue();
|
||||
|
||||
//if (IsTrueExpression(left)) left = GetQuotedTrueValue();
|
||||
//else if (IsFalseExpression(left)) left = GetQuotedFalseValue();
|
||||
|
||||
}
|
||||
|
||||
switch (operand)
|
||||
{
|
||||
case "MOD":
|
||||
case "COALESCE":
|
||||
return string.Format("{0}({1},{2})", operand, left, right);
|
||||
default:
|
||||
return left + " " + operand + " " + right;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitExpressionList(ReadOnlyCollection<Expression> original)
|
||||
{
|
||||
var list = new List<Object>();
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
if (original[i].NodeType == ExpressionType.NewArrayInit ||
|
||||
original[i].NodeType == ExpressionType.NewArrayBounds)
|
||||
{
|
||||
|
||||
list.AddRange(VisitNewArrayFromExpressionList(original[i] as NewArrayExpression));
|
||||
}
|
||||
else
|
||||
list.Add(Visit(original[i]));
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected virtual string VisitNew(NewExpression nex)
|
||||
{
|
||||
// TODO : check !
|
||||
var member = Expression.Convert(nex, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
try
|
||||
{
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
|
||||
SqlParameters.Add(o);
|
||||
return string.Format("@{0}", SqlParameters.Count - 1);
|
||||
|
||||
//return GetQuotedValue(o, o.GetType());
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// FieldName ?
|
||||
List<Object> exprs = VisitExpressionList(nex.Arguments);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.AppendFormat("{0}{1}",
|
||||
r.Length > 0 ? "," : "",
|
||||
e);
|
||||
}
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitParameter(ParameterExpression p)
|
||||
{
|
||||
return p.Name;
|
||||
}
|
||||
|
||||
protected virtual string VisitConstant(ConstantExpression c)
|
||||
{
|
||||
if (c.Value == null)
|
||||
return "null";
|
||||
|
||||
SqlParameters.Add(c.Value);
|
||||
return string.Format("@{0}", SqlParameters.Count - 1);
|
||||
|
||||
//if (c.Value is bool)
|
||||
//{
|
||||
// object o = GetQuotedValue(c.Value, c.Value.GetType());
|
||||
// return string.Format("({0}={1})", GetQuotedTrueValue(), o);
|
||||
//}
|
||||
//return GetQuotedValue(c.Value, c.Value.GetType());
|
||||
}
|
||||
|
||||
protected virtual string VisitUnary(UnaryExpression u)
|
||||
{
|
||||
switch (u.NodeType)
|
||||
{
|
||||
case ExpressionType.Not:
|
||||
var o = Visit(u.Operand);
|
||||
|
||||
//use a Not equal operator instead of <> since we don't know that <> works in all sql servers
|
||||
|
||||
switch (u.Operand.NodeType)
|
||||
{
|
||||
case ExpressionType.MemberAccess:
|
||||
//In this case it wil be a false property , i.e. x => !Trashed
|
||||
SqlParameters.Add(true);
|
||||
return string.Format("NOT ({0} = @0)", o);
|
||||
default:
|
||||
//In this case it could be anything else, such as: x => !x.Path.StartsWith("-20")
|
||||
return string.Format("NOT ({0})", o);
|
||||
}
|
||||
default:
|
||||
return Visit(u.Operand);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitNewArray(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.Append(r.Length > 0 ? "," + e : e);
|
||||
}
|
||||
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitNewArrayFromExpressionList(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
return exprs;
|
||||
}
|
||||
|
||||
protected virtual string BindOperant(ExpressionType e)
|
||||
{
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ExpressionType.Equal:
|
||||
return "=";
|
||||
case ExpressionType.NotEqual:
|
||||
return "<>";
|
||||
case ExpressionType.GreaterThan:
|
||||
return ">";
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
return ">=";
|
||||
case ExpressionType.LessThan:
|
||||
return "<";
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
return "<=";
|
||||
case ExpressionType.AndAlso:
|
||||
return "AND";
|
||||
case ExpressionType.OrElse:
|
||||
return "OR";
|
||||
case ExpressionType.Add:
|
||||
return "+";
|
||||
case ExpressionType.Subtract:
|
||||
return "-";
|
||||
case ExpressionType.Multiply:
|
||||
return "*";
|
||||
case ExpressionType.Divide:
|
||||
return "/";
|
||||
case ExpressionType.Modulo:
|
||||
return "MOD";
|
||||
case ExpressionType.Coalesce:
|
||||
return "COALESCE";
|
||||
default:
|
||||
return e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
//Here's what happens with a MethodCallExpression:
|
||||
// If a method is called that contains a single argument,
|
||||
// then m.Object is the object on the left hand side of the method call, example:
|
||||
// x.Path.StartsWith(content.Path)
|
||||
// m.Object = x.Path
|
||||
// and m.Arguments.Length == 1, therefor m.Arguments[0] == content.Path
|
||||
// If a method is called that contains multiple arguments, then m.Object == null and the
|
||||
// m.Arguments collection contains the left hand side of the method call, example:
|
||||
// x.Path.SqlStartsWith(content.Path, TextColumnType.NVarchar)
|
||||
// m.Object == null
|
||||
// m.Arguments.Length == 3, therefor, m.Arguments[0] == x.Path, m.Arguments[1] == content.Path, m.Arguments[2] == TextColumnType.NVarchar
|
||||
// So, we need to cater for these scenarios.
|
||||
|
||||
var objectForMethod = m.Object ?? m.Arguments[0];
|
||||
var visitedObjectForMethod = Visit(objectForMethod);
|
||||
var methodArgs = m.Object == null
|
||||
? m.Arguments.Skip(1).ToArray()
|
||||
: m.Arguments.ToArray();
|
||||
|
||||
switch (m.Method.Name)
|
||||
{
|
||||
case "ToString":
|
||||
SqlParameters.Add(objectForMethod.ToString());
|
||||
return string.Format("@{0}", SqlParameters.Count - 1);
|
||||
case "ToUpper":
|
||||
return string.Format("upper({0})", visitedObjectForMethod);
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", visitedObjectForMethod);
|
||||
case "SqlWildcard":
|
||||
case "StartsWith":
|
||||
case "EndsWith":
|
||||
case "Contains":
|
||||
case "Equals":
|
||||
case "SqlStartsWith":
|
||||
case "SqlEndsWith":
|
||||
case "SqlContains":
|
||||
case "SqlEquals":
|
||||
case "InvariantStartsWith":
|
||||
case "InvariantEndsWith":
|
||||
case "InvariantContains":
|
||||
case "InvariantEquals":
|
||||
|
||||
string compareValue;
|
||||
|
||||
if (methodArgs[0].NodeType != ExpressionType.Constant)
|
||||
{
|
||||
//This occurs when we are getting a value from a non constant such as: x => x.Path.StartsWith(content.Path)
|
||||
// So we'll go get the value:
|
||||
var member = Expression.Convert(methodArgs[0], typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
compareValue = getter().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
compareValue = methodArgs[0].ToString();
|
||||
}
|
||||
|
||||
//special case, if it is 'Contains' and the member that Contains is being called on is not a string, then
|
||||
// we should be doing an 'In' clause - but we currently do not support this
|
||||
if (methodArgs[0].Type != typeof(string) && TypeHelper.IsTypeAssignableFrom<IEnumerable>(methodArgs[0].Type))
|
||||
{
|
||||
throw new NotSupportedException("An array Contains method is not supported");
|
||||
}
|
||||
|
||||
//default column type
|
||||
var colType = TextColumnType.NVarchar;
|
||||
|
||||
//then check if the col type argument has been passed to the current method (this will be the case for methods like
|
||||
// SqlContains and other Sql methods)
|
||||
if (methodArgs.Length > 1)
|
||||
{
|
||||
var colTypeArg = methodArgs.FirstOrDefault(x => x is ConstantExpression && x.Type == typeof(TextColumnType));
|
||||
if (colTypeArg != null)
|
||||
{
|
||||
colType = (TextColumnType)((ConstantExpression)colTypeArg).Value;
|
||||
}
|
||||
}
|
||||
|
||||
return HandleStringComparison(visitedObjectForMethod, compareValue, m.Method.Name, colType);
|
||||
//case "Substring":
|
||||
// var startIndex = Int32.Parse(args[0].ToString()) + 1;
|
||||
// if (args.Count == 2)
|
||||
// {
|
||||
// var length = Int32.Parse(args[1].ToString());
|
||||
// return string.Format("substring({0} from {1} for {2})",
|
||||
// r,
|
||||
// startIndex,
|
||||
// length);
|
||||
// }
|
||||
// else
|
||||
// return string.Format("substring({0} from {1})",
|
||||
// r,
|
||||
// startIndex);
|
||||
//case "Round":
|
||||
//case "Floor":
|
||||
//case "Ceiling":
|
||||
//case "Coalesce":
|
||||
//case "Abs":
|
||||
//case "Sum":
|
||||
// return string.Format("{0}({1}{2})",
|
||||
// m.Method.Name,
|
||||
// r,
|
||||
// args.Count == 1 ? string.Format(",{0}", args[0]) : "");
|
||||
//case "Concat":
|
||||
// var s = new StringBuilder();
|
||||
// foreach (Object e in args)
|
||||
// {
|
||||
// s.AppendFormat(" || {0}", e);
|
||||
// }
|
||||
// return string.Format("{0}{1}", r, s);
|
||||
|
||||
//case "In":
|
||||
|
||||
// var member = Expression.Convert(m.Arguments[0], typeof(object));
|
||||
// var lambda = Expression.Lambda<Func<object>>(member);
|
||||
// var getter = lambda.Compile();
|
||||
|
||||
// var inArgs = (object[])getter();
|
||||
|
||||
// var sIn = new StringBuilder();
|
||||
// foreach (var e in inArgs)
|
||||
// {
|
||||
// SqlParameters.Add(e);
|
||||
|
||||
// sIn.AppendFormat("{0}{1}",
|
||||
// sIn.Length > 0 ? "," : "",
|
||||
// string.Format("@{0}", SqlParameters.Count - 1));
|
||||
|
||||
// //sIn.AppendFormat("{0}{1}",
|
||||
// // sIn.Length > 0 ? "," : "",
|
||||
// // GetQuotedValue(e, e.GetType()));
|
||||
// }
|
||||
|
||||
// return string.Format("{0} {1} ({2})", r, m.Method.Name, sIn.ToString());
|
||||
//case "Desc":
|
||||
// return string.Format("{0} DESC", r);
|
||||
//case "Alias":
|
||||
//case "As":
|
||||
// return string.Format("{0} As {1}", r,
|
||||
// GetQuotedColumnName(RemoveQuoteFromAlias(RemoveQuote(args[0].ToString()))));
|
||||
|
||||
default:
|
||||
|
||||
throw new ArgumentOutOfRangeException("No logic supported for " + m.Method.Name);
|
||||
|
||||
//var s2 = new StringBuilder();
|
||||
//foreach (Object e in args)
|
||||
//{
|
||||
// s2.AppendFormat(",{0}", GetQuotedValue(e, e.GetType()));
|
||||
//}
|
||||
//return string.Format("{0}({1}{2})", m.Method.Name, r, s2.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("\"{0}\"", tableName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("\"{0}\"", columnName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("\"{0}\"", name);
|
||||
}
|
||||
|
||||
//private string GetQuotedTrueValue()
|
||||
//{
|
||||
// return GetQuotedValue(true, typeof(bool));
|
||||
//}
|
||||
|
||||
//private string GetQuotedFalseValue()
|
||||
//{
|
||||
// return GetQuotedValue(false, typeof(bool));
|
||||
//}
|
||||
|
||||
//public virtual string GetQuotedValue(object value, Type fieldType)
|
||||
//{
|
||||
// return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
|
||||
//}
|
||||
|
||||
//private string GetTrueExpression()
|
||||
//{
|
||||
// object o = GetQuotedTrueValue();
|
||||
// return string.Format("({0}={1})", o, o);
|
||||
//}
|
||||
|
||||
//private string GetFalseExpression()
|
||||
//{
|
||||
|
||||
// return string.Format("({0}={1})",
|
||||
// GetQuotedTrueValue(),
|
||||
// GetQuotedFalseValue());
|
||||
//}
|
||||
|
||||
//private bool IsTrueExpression(string exp)
|
||||
//{
|
||||
// return (exp == GetTrueExpression());
|
||||
//}
|
||||
|
||||
//private bool IsFalseExpression(string exp)
|
||||
//{
|
||||
// return (exp == GetFalseExpression());
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logic that is shared with the expression helpers
|
||||
/// </summary>
|
||||
internal class BaseExpressionHelper
|
||||
internal class BaseExpressionHelper
|
||||
{
|
||||
protected List<object> SqlParameters = new List<object>();
|
||||
|
||||
public object[] GetSqlParameters()
|
||||
{
|
||||
return SqlParameters.ToArray();
|
||||
}
|
||||
|
||||
protected string HandleStringComparison(string col, string val, string verb, TextColumnType columnType)
|
||||
{
|
||||
switch (verb)
|
||||
{
|
||||
case "SqlWildcard":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, RemoveQuote(val), columnType);
|
||||
SqlParameters.Add(RemoveQuote(val));
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, SqlParameters.Count - 1, columnType);
|
||||
case "Equals":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, RemoveQuote(val), columnType);
|
||||
SqlParameters.Add(RemoveQuote(val));
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, SqlParameters.Count - 1, columnType);
|
||||
case "StartsWith":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, RemoveQuote(val), columnType);
|
||||
SqlParameters.Add(string.Format("{0}{1}",
|
||||
RemoveQuote(val),
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetWildcardPlaceholder()));
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, SqlParameters.Count - 1, columnType);
|
||||
case "EndsWith":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, RemoveQuote(val), columnType);
|
||||
SqlParameters.Add(string.Format("{0}{1}",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetWildcardPlaceholder(),
|
||||
RemoveQuote(val)));
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, SqlParameters.Count - 1, columnType);
|
||||
case "Contains":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, RemoveQuote(val), columnType);
|
||||
SqlParameters.Add(string.Format("{0}{1}{0}",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetWildcardPlaceholder(),
|
||||
RemoveQuote(val)));
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, SqlParameters.Count - 1, columnType);
|
||||
case "InvariantEquals":
|
||||
case "SqlEquals":
|
||||
//recurse
|
||||
@@ -44,61 +578,54 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string GetQuotedValue(object value, Type fieldType, Func<object, string> escapeCallback = null, Func<Type, bool> shouldQuoteCallback = null)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
//public virtual string GetQuotedValue(object value, Type fieldType, Func<object, string> escapeCallback = null, Func<Type, bool> shouldQuoteCallback = null)
|
||||
//{
|
||||
// if (value == null) return "NULL";
|
||||
|
||||
if (escapeCallback == null)
|
||||
{
|
||||
escapeCallback = EscapeParam;
|
||||
}
|
||||
if (shouldQuoteCallback == null)
|
||||
{
|
||||
shouldQuoteCallback = ShouldQuoteValue;
|
||||
}
|
||||
// if (escapeCallback == null)
|
||||
// {
|
||||
// escapeCallback = EscapeParam;
|
||||
// }
|
||||
// if (shouldQuoteCallback == null)
|
||||
// {
|
||||
// shouldQuoteCallback = ShouldQuoteValue;
|
||||
// }
|
||||
|
||||
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
|
||||
{
|
||||
//if (TypeSerializer.CanCreateFromString(fieldType))
|
||||
//{
|
||||
// return "'" + escapeCallback(TypeSerializer.SerializeToString(value)) + "'";
|
||||
//}
|
||||
// if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
|
||||
// {
|
||||
// //if (TypeSerializer.CanCreateFromString(fieldType))
|
||||
// //{
|
||||
// // return "'" + escapeCallback(TypeSerializer.SerializeToString(value)) + "'";
|
||||
// //}
|
||||
|
||||
throw new NotSupportedException(
|
||||
string.Format("Property of type: {0} is not supported", fieldType.FullName));
|
||||
}
|
||||
// throw new NotSupportedException(
|
||||
// string.Format("Property of type: {0} is not supported", fieldType.FullName));
|
||||
// }
|
||||
|
||||
if (fieldType == typeof(int))
|
||||
return ((int)value).ToString(CultureInfo.InvariantCulture);
|
||||
// if (fieldType == typeof(int))
|
||||
// return ((int)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(float))
|
||||
return ((float)value).ToString(CultureInfo.InvariantCulture);
|
||||
// if (fieldType == typeof(float))
|
||||
// return ((float)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(double))
|
||||
return ((double)value).ToString(CultureInfo.InvariantCulture);
|
||||
// if (fieldType == typeof(double))
|
||||
// return ((double)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
// if (fieldType == typeof(decimal))
|
||||
// return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(DateTime))
|
||||
{
|
||||
return "'" + escapeCallback(((DateTime)value).ToIsoString()) + "'";
|
||||
}
|
||||
// if (fieldType == typeof(DateTime))
|
||||
// {
|
||||
// return "'" + escapeCallback(((DateTime)value).ToIsoString()) + "'";
|
||||
// }
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
// if (fieldType == typeof(bool))
|
||||
// return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
return shouldQuoteCallback(fieldType)
|
||||
? "'" + escapeCallback(value) + "'"
|
||||
: value.ToString();
|
||||
}
|
||||
|
||||
public virtual string EscapeParam(object paramValue)
|
||||
{
|
||||
return paramValue == null
|
||||
? string.Empty
|
||||
: SqlSyntaxContext.SqlSyntaxProvider.EscapeString(paramValue.ToString());
|
||||
}
|
||||
// return shouldQuoteCallback(fieldType)
|
||||
// ? "'" + escapeCallback(value) + "'"
|
||||
// : value.ToString();
|
||||
//}
|
||||
|
||||
public virtual bool ShouldQuoteValue(Type fieldType)
|
||||
{
|
||||
@@ -107,16 +634,12 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
|
||||
protected virtual string RemoveQuote(string exp)
|
||||
{
|
||||
if (exp.StartsWith("'") && exp.EndsWith("'"))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
protected virtual string RemoveQuoteFromAlias(string exp)
|
||||
{
|
||||
//if (exp.StartsWith("'") && exp.EndsWith("'"))
|
||||
//{
|
||||
// exp = exp.Remove(0, 1);
|
||||
// exp = exp.Remove(exp.Length - 1, 1);
|
||||
//}
|
||||
//return exp;
|
||||
|
||||
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
|
||||
&&
|
||||
@@ -127,5 +650,18 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
//protected virtual string RemoveQuoteFromAlias(string exp)
|
||||
//{
|
||||
|
||||
// if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
|
||||
// &&
|
||||
// (exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
|
||||
// {
|
||||
// exp = exp.Remove(0, 1);
|
||||
// exp = exp.Remove(exp.Length - 1, 1);
|
||||
// }
|
||||
// return exp;
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
/// <summary>
|
||||
/// SD: This is a horrible hack but unless we break compatibility with anyone who's actually implemented IQuery{T} there's not much we can do.
|
||||
/// The IQuery{T} interface is useless without having a GetWhereClauses method and cannot be used for tests.
|
||||
/// We have to wait till v8 to make this change I suppose.
|
||||
/// </summary>
|
||||
internal static class QueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all translated where clauses and their sql parameters
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Tuple<string, object[]>> GetWhereClauses<T>(this IQuery<T> query)
|
||||
{
|
||||
var q = query as Query<T>;
|
||||
if (q == null)
|
||||
{
|
||||
throw new NotSupportedException(typeof(IQuery<T>) + " cannot be cast to " + typeof(Query<T>));
|
||||
}
|
||||
return q.GetWhereClauses();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a query for building Linq translatable SQL queries
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IQuery<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a where clause to the query
|
||||
/// </summary>
|
||||
/// <param name="predicate"></param>
|
||||
/// <returns>This instance so calls to this method are chainable</returns>
|
||||
IQuery<T> Where(Expression<Func<T, bool>> predicate);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,149 +10,21 @@ using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
internal class ModelToSqlExpressionHelper<T> : BaseExpressionHelper
|
||||
internal class ModelToSqlExpressionHelper<T> : BaseExpressionHelper<T>
|
||||
{
|
||||
private string sep = " ";
|
||||
private BaseMapper _mapper;
|
||||
|
||||
private readonly BaseMapper _mapper;
|
||||
|
||||
public ModelToSqlExpressionHelper()
|
||||
{
|
||||
_mapper = MappingResolver.Current.ResolveMapperByType(typeof(T));
|
||||
}
|
||||
|
||||
protected internal virtual string Visit(Expression exp)
|
||||
|
||||
protected override string VisitMemberAccess(MemberExpression m)
|
||||
{
|
||||
|
||||
if (exp == null) return string.Empty;
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Lambda:
|
||||
return VisitLambda(exp as LambdaExpression);
|
||||
case ExpressionType.MemberAccess:
|
||||
return VisitMemberAccess(exp as MemberExpression);
|
||||
case ExpressionType.Constant:
|
||||
return VisitConstant(exp as ConstantExpression);
|
||||
case ExpressionType.Add:
|
||||
case ExpressionType.AddChecked:
|
||||
case ExpressionType.Subtract:
|
||||
case ExpressionType.SubtractChecked:
|
||||
case ExpressionType.Multiply:
|
||||
case ExpressionType.MultiplyChecked:
|
||||
case ExpressionType.Divide:
|
||||
case ExpressionType.Modulo:
|
||||
case ExpressionType.And:
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.Or:
|
||||
case ExpressionType.OrElse:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.Coalesce:
|
||||
case ExpressionType.ArrayIndex:
|
||||
case ExpressionType.RightShift:
|
||||
case ExpressionType.LeftShift:
|
||||
case ExpressionType.ExclusiveOr:
|
||||
return VisitBinary(exp as BinaryExpression);
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
case ExpressionType.Not:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
case ExpressionType.ArrayLength:
|
||||
case ExpressionType.Quote:
|
||||
case ExpressionType.TypeAs:
|
||||
return VisitUnary(exp as UnaryExpression);
|
||||
case ExpressionType.Parameter:
|
||||
return VisitParameter(exp as ParameterExpression);
|
||||
case ExpressionType.Call:
|
||||
return VisitMethodCall(exp as MethodCallExpression);
|
||||
case ExpressionType.New:
|
||||
return VisitNew(exp as NewExpression);
|
||||
case ExpressionType.NewArrayInit:
|
||||
case ExpressionType.NewArrayBounds:
|
||||
return VisitNewArray(exp as NewArrayExpression);
|
||||
default:
|
||||
return exp.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitLambda(LambdaExpression lambda)
|
||||
{
|
||||
if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ")
|
||||
{
|
||||
MemberExpression m = lambda.Body as MemberExpression;
|
||||
|
||||
if (m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
return string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
|
||||
}
|
||||
return Visit(lambda.Body);
|
||||
}
|
||||
|
||||
protected virtual string VisitBinary(BinaryExpression b)
|
||||
{
|
||||
string left, right;
|
||||
var operand = BindOperant(b.NodeType); //sep= " " ??
|
||||
if (operand == "AND" || operand == "OR")
|
||||
{
|
||||
MemberExpression m = b.Left as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
left = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
}
|
||||
m = b.Right as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
right = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
|
||||
if (operand == "=" && right == "null") operand = "is";
|
||||
else if (operand == "<>" && right == "null") operand = "is not";
|
||||
else if (operand == "=" || operand == "<>")
|
||||
{
|
||||
if (IsTrueExpression(right)) right = GetQuotedTrueValue();
|
||||
else if (IsFalseExpression(right)) right = GetQuotedFalseValue();
|
||||
|
||||
if (IsTrueExpression(left)) left = GetQuotedTrueValue();
|
||||
else if (IsFalseExpression(left)) left = GetQuotedFalseValue();
|
||||
|
||||
}
|
||||
|
||||
switch (operand)
|
||||
{
|
||||
case "MOD":
|
||||
case "COALESCE":
|
||||
return string.Format("{0}({1},{2})", operand, left, right);
|
||||
default:
|
||||
return left + sep + operand + sep + right;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitMemberAccess(MemberExpression m)
|
||||
{
|
||||
if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter && m.Expression.Type == typeof(T))
|
||||
if (m.Expression != null &&
|
||||
m.Expression.NodeType == ExpressionType.Parameter
|
||||
&& m.Expression.Type == typeof(T))
|
||||
{
|
||||
var field = _mapper.Map(m.Member.Name);
|
||||
return field;
|
||||
@@ -168,324 +40,18 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
return GetQuotedValue(o, o != null ? o.GetType() : null);
|
||||
|
||||
SqlParameters.Add(o);
|
||||
return string.Format("@{0}", SqlParameters.Count - 1);
|
||||
|
||||
//return GetQuotedValue(o, o != null ? o.GetType() : null);
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitNew(NewExpression nex)
|
||||
{
|
||||
// TODO : check !
|
||||
var member = Expression.Convert(nex, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
try
|
||||
{
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
return GetQuotedValue(o, o.GetType());
|
||||
}
|
||||
catch (System.InvalidOperationException)
|
||||
{ // FieldName ?
|
||||
List<Object> exprs = VisitExpressionList(nex.Arguments);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.AppendFormat("{0}{1}", r.Length > 0 ? "," : "", e);
|
||||
}
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitParameter(ParameterExpression p)
|
||||
{
|
||||
return p.Name;
|
||||
}
|
||||
|
||||
protected virtual string VisitConstant(ConstantExpression c)
|
||||
{
|
||||
if (c.Value == null)
|
||||
return "null";
|
||||
if (c.Value is bool)
|
||||
{
|
||||
object o = GetQuotedValue(c.Value, c.Value.GetType());
|
||||
return string.Format("({0}={1})", GetQuotedTrueValue(), o);
|
||||
}
|
||||
return GetQuotedValue(c.Value, c.Value.GetType());
|
||||
}
|
||||
|
||||
protected virtual string VisitUnary(UnaryExpression u)
|
||||
{
|
||||
switch (u.NodeType)
|
||||
{
|
||||
case ExpressionType.Not:
|
||||
string o = Visit(u.Operand);
|
||||
if (IsFieldName(o)) o = o + "=" + GetQuotedValue(true, typeof(bool));
|
||||
return "NOT (" + o + ")";
|
||||
default:
|
||||
return Visit(u.Operand);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
List<Object> args = this.VisitExpressionList(m.Arguments);
|
||||
|
||||
Object r;
|
||||
if (m.Object != null)
|
||||
r = Visit(m.Object);
|
||||
else
|
||||
{
|
||||
r = args[0];
|
||||
args.RemoveAt(0);
|
||||
}
|
||||
|
||||
switch (m.Method.Name)
|
||||
{
|
||||
case "ToUpper":
|
||||
return string.Format("upper({0})", r);
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", r);
|
||||
case "SqlWildcard":
|
||||
case "StartsWith":
|
||||
case "EndsWith":
|
||||
case "Contains":
|
||||
case "Equals":
|
||||
case "SqlStartsWith":
|
||||
case "SqlEndsWith":
|
||||
case "SqlContains":
|
||||
case "SqlEquals":
|
||||
case "InvariantStartsWith":
|
||||
case "InvariantEndsWith":
|
||||
case "InvariantContains":
|
||||
case "InvariantEquals":
|
||||
//default
|
||||
var colType = TextColumnType.NVarchar;
|
||||
//then check if this arg has been passed in
|
||||
if (m.Arguments.Count > 1)
|
||||
{
|
||||
var colTypeArg = m.Arguments.FirstOrDefault(x => x is ConstantExpression && x.Type == typeof(TextColumnType));
|
||||
if (colTypeArg != null)
|
||||
{
|
||||
colType = (TextColumnType) ((ConstantExpression) colTypeArg).Value;
|
||||
}
|
||||
}
|
||||
return HandleStringComparison(r.ToString(), args[0].ToString(), m.Method.Name, colType);
|
||||
case "Substring":
|
||||
var startIndex = Int32.Parse(args[0].ToString()) + 1;
|
||||
if (args.Count == 2)
|
||||
{
|
||||
var length = Int32.Parse(args[1].ToString());
|
||||
return string.Format("substring({0} from {1} for {2})",
|
||||
r,
|
||||
startIndex,
|
||||
length);
|
||||
}
|
||||
else
|
||||
return string.Format("substring({0} from {1})",
|
||||
r,
|
||||
startIndex);
|
||||
case "Round":
|
||||
case "Floor":
|
||||
case "Ceiling":
|
||||
case "Coalesce":
|
||||
case "Abs":
|
||||
case "Sum":
|
||||
return string.Format("{0}({1}{2})",
|
||||
m.Method.Name,
|
||||
r,
|
||||
args.Count == 1 ? string.Format(",{0}", args[0]) : "");
|
||||
case "Concat":
|
||||
var s = new StringBuilder();
|
||||
foreach (Object e in args)
|
||||
{
|
||||
s.AppendFormat(" || {0}", e);
|
||||
}
|
||||
return string.Format("{0}{1}", r, s.ToString());
|
||||
|
||||
case "In":
|
||||
|
||||
var member = Expression.Convert(m.Arguments[1], typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
|
||||
var inArgs = getter() as object[];
|
||||
|
||||
var sIn = new StringBuilder();
|
||||
foreach (Object e in inArgs)
|
||||
{
|
||||
if (e.GetType().ToString() != "System.Collections.Generic.List`1[System.Object]")
|
||||
{
|
||||
sIn.AppendFormat("{0}{1}",
|
||||
sIn.Length > 0 ? "," : "",
|
||||
GetQuotedValue(e, e.GetType()));
|
||||
}
|
||||
else
|
||||
{
|
||||
var listArgs = e as IList<Object>;
|
||||
foreach (Object el in listArgs)
|
||||
{
|
||||
sIn.AppendFormat("{0}{1}",
|
||||
sIn.Length > 0 ? "," : "",
|
||||
GetQuotedValue(el, el.GetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format("{0} {1} ({2})", r, m.Method.Name, sIn.ToString());
|
||||
case "Desc":
|
||||
return string.Format("{0} DESC", r);
|
||||
case "Alias":
|
||||
case "As":
|
||||
return string.Format("{0} As {1}", r,
|
||||
GetQuotedColumnName(RemoveQuoteFromAlias(RemoveQuote(args[0].ToString()))));
|
||||
case "ToString":
|
||||
return r.ToString();
|
||||
default:
|
||||
var s2 = new StringBuilder();
|
||||
foreach (Object e in args)
|
||||
{
|
||||
s2.AppendFormat(",{0}", GetQuotedValue(e, e.GetType()));
|
||||
}
|
||||
return string.Format("{0}({1}{2})", m.Method.Name, r, s2.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitExpressionList(ReadOnlyCollection<Expression> original)
|
||||
{
|
||||
var list = new List<Object>();
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
if (original[i].NodeType == ExpressionType.NewArrayInit ||
|
||||
original[i].NodeType == ExpressionType.NewArrayBounds)
|
||||
{
|
||||
|
||||
list.AddRange(VisitNewArrayFromExpressionList(original[i] as NewArrayExpression));
|
||||
}
|
||||
else
|
||||
list.Add(Visit(original[i]));
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected virtual string VisitNewArray(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.Append(r.Length > 0 ? "," + e : e);
|
||||
}
|
||||
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitNewArrayFromExpressionList(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
return exprs;
|
||||
}
|
||||
|
||||
|
||||
protected virtual string BindOperant(ExpressionType e)
|
||||
{
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ExpressionType.Equal:
|
||||
return "=";
|
||||
case ExpressionType.NotEqual:
|
||||
return "<>";
|
||||
case ExpressionType.GreaterThan:
|
||||
return ">";
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
return ">=";
|
||||
case ExpressionType.LessThan:
|
||||
return "<";
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
return "<=";
|
||||
case ExpressionType.AndAlso:
|
||||
return "AND";
|
||||
case ExpressionType.OrElse:
|
||||
return "OR";
|
||||
case ExpressionType.Add:
|
||||
return "+";
|
||||
case ExpressionType.Subtract:
|
||||
return "-";
|
||||
case ExpressionType.Multiply:
|
||||
return "*";
|
||||
case ExpressionType.Divide:
|
||||
return "/";
|
||||
case ExpressionType.Modulo:
|
||||
return "MOD";
|
||||
case ExpressionType.Coalesce:
|
||||
return "COALESCE";
|
||||
default:
|
||||
return e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("\"{0}\"", tableName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("\"{0}\"", columnName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("\"{0}\"", name);
|
||||
}
|
||||
|
||||
private string GetQuotedTrueValue()
|
||||
{
|
||||
return GetQuotedValue(true, typeof(bool));
|
||||
}
|
||||
|
||||
private string GetQuotedFalseValue()
|
||||
{
|
||||
return GetQuotedValue(false, typeof(bool));
|
||||
}
|
||||
|
||||
public virtual string GetQuotedValue(object value, Type fieldType)
|
||||
{
|
||||
return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
|
||||
}
|
||||
|
||||
private string GetTrueExpression()
|
||||
{
|
||||
object o = GetQuotedTrueValue();
|
||||
return string.Format("({0}={1})", o, o);
|
||||
}
|
||||
|
||||
private string GetFalseExpression()
|
||||
{
|
||||
|
||||
return string.Format("({0}={1})",
|
||||
GetQuotedTrueValue(),
|
||||
GetQuotedFalseValue());
|
||||
}
|
||||
|
||||
private bool IsTrueExpression(string exp)
|
||||
{
|
||||
return (exp == GetTrueExpression());
|
||||
}
|
||||
|
||||
private bool IsFalseExpression(string exp)
|
||||
{
|
||||
return (exp == GetFalseExpression());
|
||||
}
|
||||
|
||||
protected bool IsFieldName(string quotedExp)
|
||||
{
|
||||
//Not entirely sure this is reliable, but its better then simply returning true
|
||||
return quotedExp.LastIndexOf("'", StringComparison.InvariantCultureIgnoreCase) + 1 != quotedExp.Length;
|
||||
}
|
||||
|
||||
//protected bool IsFieldName(string quotedExp)
|
||||
//{
|
||||
// //Not entirely sure this is reliable, but its better then simply returning true
|
||||
// return quotedExp.LastIndexOf("'", StringComparison.InvariantCultureIgnoreCase) + 1 != quotedExp.Length;
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
@@ -8,159 +9,28 @@ using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
internal class PocoToSqlExpressionHelper<T> : BaseExpressionHelper
|
||||
internal class PocoToSqlExpressionHelper<T> : BaseExpressionHelper<T>
|
||||
{
|
||||
private string sep = " ";
|
||||
private Database.PocoData pd;
|
||||
private readonly Database.PocoData _pd;
|
||||
|
||||
public PocoToSqlExpressionHelper()
|
||||
{
|
||||
pd = new Database.PocoData(typeof(T));
|
||||
_pd = new Database.PocoData(typeof(T));
|
||||
}
|
||||
|
||||
protected internal virtual string Visit(Expression exp)
|
||||
{
|
||||
|
||||
if (exp == null) return string.Empty;
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Lambda:
|
||||
return VisitLambda(exp as LambdaExpression);
|
||||
case ExpressionType.MemberAccess:
|
||||
return VisitMemberAccess(exp as MemberExpression);
|
||||
case ExpressionType.Constant:
|
||||
return VisitConstant(exp as ConstantExpression);
|
||||
case ExpressionType.Add:
|
||||
case ExpressionType.AddChecked:
|
||||
case ExpressionType.Subtract:
|
||||
case ExpressionType.SubtractChecked:
|
||||
case ExpressionType.Multiply:
|
||||
case ExpressionType.MultiplyChecked:
|
||||
case ExpressionType.Divide:
|
||||
case ExpressionType.Modulo:
|
||||
case ExpressionType.And:
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.Or:
|
||||
case ExpressionType.OrElse:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.Coalesce:
|
||||
case ExpressionType.ArrayIndex:
|
||||
case ExpressionType.RightShift:
|
||||
case ExpressionType.LeftShift:
|
||||
case ExpressionType.ExclusiveOr:
|
||||
return VisitBinary(exp as BinaryExpression);
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
case ExpressionType.Not:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
case ExpressionType.ArrayLength:
|
||||
case ExpressionType.Quote:
|
||||
case ExpressionType.TypeAs:
|
||||
return VisitUnary(exp as UnaryExpression);
|
||||
case ExpressionType.Parameter:
|
||||
return VisitParameter(exp as ParameterExpression);
|
||||
case ExpressionType.Call:
|
||||
return VisitMethodCall(exp as MethodCallExpression);
|
||||
case ExpressionType.New:
|
||||
return VisitNew(exp as NewExpression);
|
||||
case ExpressionType.NewArrayInit:
|
||||
case ExpressionType.NewArrayBounds:
|
||||
return VisitNewArray(exp as NewArrayExpression);
|
||||
default:
|
||||
return exp.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitLambda(LambdaExpression lambda)
|
||||
{
|
||||
if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ")
|
||||
{
|
||||
MemberExpression m = lambda.Body as MemberExpression;
|
||||
|
||||
if (m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
return string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
|
||||
}
|
||||
return Visit(lambda.Body);
|
||||
}
|
||||
|
||||
protected virtual string VisitBinary(BinaryExpression b)
|
||||
{
|
||||
string left, right;
|
||||
var operand = BindOperant(b.NodeType); //sep= " " ??
|
||||
if (operand == "AND" || operand == "OR")
|
||||
{
|
||||
MemberExpression m = b.Left as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
left = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
}
|
||||
m = b.Right as MemberExpression;
|
||||
if (m != null && m.Expression != null)
|
||||
{
|
||||
string r = VisitMemberAccess(m);
|
||||
right = string.Format("{0}={1}", r, GetQuotedTrueValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
left = Visit(b.Left);
|
||||
right = Visit(b.Right);
|
||||
}
|
||||
|
||||
if (operand == "=" && right == "null") operand = "is";
|
||||
else if (operand == "<>" && right == "null") operand = "is not";
|
||||
else if (operand == "=" || operand == "<>")
|
||||
{
|
||||
if (IsTrueExpression(right)) right = GetQuotedTrueValue();
|
||||
else if (IsFalseExpression(right)) right = GetQuotedFalseValue();
|
||||
|
||||
if (IsTrueExpression(left)) left = GetQuotedTrueValue();
|
||||
else if (IsFalseExpression(left)) left = GetQuotedFalseValue();
|
||||
|
||||
}
|
||||
|
||||
switch (operand)
|
||||
{
|
||||
case "MOD":
|
||||
case "COALESCE":
|
||||
return string.Format("{0}({1},{2})", operand, left, right);
|
||||
default:
|
||||
return left + sep + operand + sep + right;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitMemberAccess(MemberExpression m)
|
||||
|
||||
protected override string VisitMemberAccess(MemberExpression m)
|
||||
{
|
||||
if (m.Expression != null &&
|
||||
m.Expression.NodeType == ExpressionType.Parameter
|
||||
&& m.Expression.Type == typeof(T))
|
||||
{
|
||||
string field = GetFieldName(pd, m.Member.Name);
|
||||
string field = GetFieldName(_pd, m.Member.Name);
|
||||
return field;
|
||||
}
|
||||
|
||||
if (m.Expression != null && m.Expression.NodeType == ExpressionType.Convert)
|
||||
{
|
||||
string field = GetFieldName(pd, m.Member.Name);
|
||||
string field = GetFieldName(_pd, m.Member.Name);
|
||||
return field;
|
||||
}
|
||||
|
||||
@@ -168,303 +38,14 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
return GetQuotedValue(o, o != null ? o.GetType() : null);
|
||||
|
||||
SqlParameters.Add(o);
|
||||
return string.Format("@{0}", SqlParameters.Count - 1);
|
||||
|
||||
//return GetQuotedValue(o, o != null ? o.GetType() : null);
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitNew(NewExpression nex)
|
||||
{
|
||||
// TODO : check !
|
||||
var member = Expression.Convert(nex, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
try
|
||||
{
|
||||
var getter = lambda.Compile();
|
||||
object o = getter();
|
||||
return GetQuotedValue(o, o.GetType());
|
||||
}
|
||||
catch (System.InvalidOperationException)
|
||||
{ // FieldName ?
|
||||
List<Object> exprs = VisitExpressionList(nex.Arguments);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.AppendFormat("{0}{1}",
|
||||
r.Length > 0 ? "," : "",
|
||||
e);
|
||||
}
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitParameter(ParameterExpression p)
|
||||
{
|
||||
return p.Name;
|
||||
}
|
||||
|
||||
protected virtual string VisitConstant(ConstantExpression c)
|
||||
{
|
||||
if (c.Value == null)
|
||||
return "null";
|
||||
else if (c.Value.GetType() == typeof(bool))
|
||||
{
|
||||
object o = GetQuotedValue(c.Value, c.Value.GetType());
|
||||
return string.Format("({0}={1})", GetQuotedTrueValue(), o);
|
||||
}
|
||||
else
|
||||
return GetQuotedValue(c.Value, c.Value.GetType());
|
||||
}
|
||||
|
||||
protected virtual string VisitUnary(UnaryExpression u)
|
||||
{
|
||||
switch (u.NodeType)
|
||||
{
|
||||
case ExpressionType.Not:
|
||||
string o = Visit(u.Operand);
|
||||
if (IsFieldName(o)) o = o + "=" + GetQuotedValue(true, typeof(bool));
|
||||
return "NOT (" + o + ")";
|
||||
default:
|
||||
return Visit(u.Operand);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual string VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
List<Object> args = this.VisitExpressionList(m.Arguments);
|
||||
|
||||
Object r;
|
||||
if (m.Object != null)
|
||||
r = Visit(m.Object);
|
||||
else
|
||||
{
|
||||
r = args[0];
|
||||
args.RemoveAt(0);
|
||||
}
|
||||
|
||||
//TODO: We should probably add the same logic we've done for ModelToSqlExpressionHelper with checking for:
|
||||
// InvariantStartsWith, InvariantEndsWith, SqlWildcard, etc...
|
||||
// since we should be able to easily handle that with the Poco objects too.
|
||||
|
||||
switch (m.Method.Name)
|
||||
{
|
||||
case "ToUpper":
|
||||
return string.Format("upper({0})", r);
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", r);
|
||||
case "SqlWildcard":
|
||||
case "StartsWith":
|
||||
case "EndsWith":
|
||||
case "Contains":
|
||||
case "Equals":
|
||||
case "SqlStartsWith":
|
||||
case "SqlEndsWith":
|
||||
case "SqlContains":
|
||||
case "SqlEquals":
|
||||
case "InvariantStartsWith":
|
||||
case "InvariantEndsWith":
|
||||
case "InvariantContains":
|
||||
case "InvariantEquals":
|
||||
//default
|
||||
var colType = TextColumnType.NVarchar;
|
||||
//then check if this arg has been passed in
|
||||
if (m.Arguments.Count > 1)
|
||||
{
|
||||
var colTypeArg = m.Arguments.FirstOrDefault(x => x is ConstantExpression && x.Type == typeof(TextColumnType));
|
||||
if (colTypeArg != null)
|
||||
{
|
||||
colType = (TextColumnType)((ConstantExpression)colTypeArg).Value;
|
||||
}
|
||||
}
|
||||
return HandleStringComparison(r.ToString(), args[0].ToString(), m.Method.Name, colType);
|
||||
case "Substring":
|
||||
var startIndex = Int32.Parse(args[0].ToString()) + 1;
|
||||
if (args.Count == 2)
|
||||
{
|
||||
var length = Int32.Parse(args[1].ToString());
|
||||
return string.Format("substring({0} from {1} for {2})",
|
||||
r,
|
||||
startIndex,
|
||||
length);
|
||||
}
|
||||
else
|
||||
return string.Format("substring({0} from {1})",
|
||||
r,
|
||||
startIndex);
|
||||
case "Round":
|
||||
case "Floor":
|
||||
case "Ceiling":
|
||||
case "Coalesce":
|
||||
case "Abs":
|
||||
case "Sum":
|
||||
return string.Format("{0}({1}{2})",
|
||||
m.Method.Name,
|
||||
r,
|
||||
args.Count == 1 ? string.Format(",{0}", args[0]) : "");
|
||||
case "Concat":
|
||||
var s = new StringBuilder();
|
||||
foreach (Object e in args)
|
||||
{
|
||||
s.AppendFormat(" || {0}", e);
|
||||
}
|
||||
return string.Format("{0}{1}", r, s.ToString());
|
||||
|
||||
case "In":
|
||||
|
||||
var member = Expression.Convert(m.Arguments[1], typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
|
||||
var inArgs = getter() as object[];
|
||||
|
||||
var sIn = new StringBuilder();
|
||||
foreach (Object e in inArgs)
|
||||
{
|
||||
if (e.GetType().ToString() != "System.Collections.Generic.List`1[System.Object]")
|
||||
{
|
||||
sIn.AppendFormat("{0}{1}",
|
||||
sIn.Length > 0 ? "," : "",
|
||||
GetQuotedValue(e, e.GetType()));
|
||||
}
|
||||
else
|
||||
{
|
||||
var listArgs = e as IList<Object>;
|
||||
foreach (Object el in listArgs)
|
||||
{
|
||||
sIn.AppendFormat("{0}{1}",
|
||||
sIn.Length > 0 ? "," : "",
|
||||
GetQuotedValue(el, el.GetType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Format("{0} {1} ({2})", r, m.Method.Name, sIn.ToString());
|
||||
case "Desc":
|
||||
return string.Format("{0} DESC", r);
|
||||
case "Alias":
|
||||
case "As":
|
||||
return string.Format("{0} As {1}", r,
|
||||
GetQuotedColumnName(RemoveQuoteFromAlias(RemoveQuote(args[0].ToString()))));
|
||||
case "ToString":
|
||||
return r.ToString();
|
||||
default:
|
||||
var s2 = new StringBuilder();
|
||||
foreach (Object e in args)
|
||||
{
|
||||
s2.AppendFormat(",{0}", GetQuotedValue(e, e.GetType()));
|
||||
}
|
||||
return string.Format("{0}({1}{2})", m.Method.Name, r, s2.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitExpressionList(ReadOnlyCollection<Expression> original)
|
||||
{
|
||||
var list = new List<Object>();
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
if (original[i].NodeType == ExpressionType.NewArrayInit ||
|
||||
original[i].NodeType == ExpressionType.NewArrayBounds)
|
||||
{
|
||||
|
||||
list.AddRange(VisitNewArrayFromExpressionList(original[i] as NewArrayExpression));
|
||||
}
|
||||
else
|
||||
list.Add(Visit(original[i]));
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected virtual string VisitNewArray(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
var r = new StringBuilder();
|
||||
foreach (Object e in exprs)
|
||||
{
|
||||
r.Append(r.Length > 0 ? "," + e : e);
|
||||
}
|
||||
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
protected virtual List<Object> VisitNewArrayFromExpressionList(NewArrayExpression na)
|
||||
{
|
||||
|
||||
List<Object> exprs = VisitExpressionList(na.Expressions);
|
||||
return exprs;
|
||||
}
|
||||
|
||||
|
||||
protected virtual string BindOperant(ExpressionType e)
|
||||
{
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ExpressionType.Equal:
|
||||
return "=";
|
||||
case ExpressionType.NotEqual:
|
||||
return "<>";
|
||||
case ExpressionType.GreaterThan:
|
||||
return ">";
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
return ">=";
|
||||
case ExpressionType.LessThan:
|
||||
return "<";
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
return "<=";
|
||||
case ExpressionType.AndAlso:
|
||||
return "AND";
|
||||
case ExpressionType.OrElse:
|
||||
return "OR";
|
||||
case ExpressionType.Add:
|
||||
return "+";
|
||||
case ExpressionType.Subtract:
|
||||
return "-";
|
||||
case ExpressionType.Multiply:
|
||||
return "*";
|
||||
case ExpressionType.Divide:
|
||||
return "/";
|
||||
case ExpressionType.Modulo:
|
||||
return "MOD";
|
||||
case ExpressionType.Coalesce:
|
||||
return "COALESCE";
|
||||
default:
|
||||
return e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("\"{0}\"", tableName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("\"{0}\"", columnName);
|
||||
}
|
||||
|
||||
public virtual string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("\"{0}\"", name);
|
||||
}
|
||||
|
||||
private string GetQuotedTrueValue()
|
||||
{
|
||||
return GetQuotedValue(true, typeof(bool));
|
||||
}
|
||||
|
||||
private string GetQuotedFalseValue()
|
||||
{
|
||||
return GetQuotedValue(false, typeof(bool));
|
||||
}
|
||||
|
||||
public virtual string GetQuotedValue(object value, Type fieldType)
|
||||
{
|
||||
return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
|
||||
}
|
||||
|
||||
|
||||
protected virtual string GetFieldName(Database.PocoData pocoData, string name)
|
||||
{
|
||||
var column = pocoData.Columns.FirstOrDefault(x => x.Value.PropertyInfo.Name == name);
|
||||
@@ -472,34 +53,10 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(pocoData.TableInfo.TableName),
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(column.Value.ColumnName));
|
||||
}
|
||||
|
||||
private string GetTrueExpression()
|
||||
{
|
||||
object o = GetQuotedTrueValue();
|
||||
return string.Format("({0}={1})", o, o);
|
||||
}
|
||||
|
||||
private string GetFalseExpression()
|
||||
{
|
||||
|
||||
return string.Format("({0}={1})",
|
||||
GetQuotedTrueValue(),
|
||||
GetQuotedFalseValue());
|
||||
}
|
||||
|
||||
private bool IsTrueExpression(string exp)
|
||||
{
|
||||
return (exp == GetTrueExpression());
|
||||
}
|
||||
|
||||
private bool IsFalseExpression(string exp)
|
||||
{
|
||||
return (exp == GetFalseExpression());
|
||||
}
|
||||
|
||||
protected bool IsFieldName(string quotedExp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//protected bool IsFieldName(string quotedExp)
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
@@ -10,37 +11,46 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class Query<T> : IQuery<T>
|
||||
{
|
||||
//private readonly ExpressionHelper<T> _expresionist = new ExpressionHelper<T>();
|
||||
private readonly ModelToSqlExpressionHelper<T> _expresionist = new ModelToSqlExpressionHelper<T>();
|
||||
private readonly List<string> _wheres = new List<string>();
|
||||
|
||||
public Query()
|
||||
: base()
|
||||
{
|
||||
|
||||
}
|
||||
private readonly List<Tuple<string, object[]>> _wheres = new List<Tuple<string, object[]>>();
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to be used instead of manually creating an instance
|
||||
/// </summary>
|
||||
public static IQuery<T> Builder
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Query<T>();
|
||||
}
|
||||
get { return new Query<T>(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a where clause to the query
|
||||
/// </summary>
|
||||
/// <param name="predicate"></param>
|
||||
/// <returns>This instance so calls to this method are chainable</returns>
|
||||
public virtual IQuery<T> Where(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
if (predicate != null)
|
||||
{
|
||||
string whereExpression = _expresionist.Visit(predicate);
|
||||
_wheres.Add(whereExpression);
|
||||
var expressionHelper = new ModelToSqlExpressionHelper<T>();
|
||||
string whereExpression = expressionHelper.Visit(predicate);
|
||||
|
||||
_wheres.Add(new Tuple<string, object[]>(whereExpression, expressionHelper.GetSqlParameters()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<string> WhereClauses()
|
||||
|
||||
/// <summary>
|
||||
/// Returns all translated where clauses and their sql parameters
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Tuple<string, object[]>> GetWhereClauses()
|
||||
{
|
||||
return _wheres;
|
||||
}
|
||||
|
||||
[Obsolete("This is no longer used, use the GetWhereClauses method which includes the SQL parameters")]
|
||||
public List<string> WhereClauses()
|
||||
{
|
||||
return _wheres.Select(x => x.Item1).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,10 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
if (sql == null)
|
||||
throw new Exception("Sql cannot be null");
|
||||
|
||||
var query1 = query as Query<T>;
|
||||
if (query1 == null)
|
||||
throw new Exception("Query cannot be null");
|
||||
|
||||
_sql = sql;
|
||||
foreach (var clause in query1.WhereClauses())
|
||||
foreach (var clause in query.GetWhereClauses())
|
||||
{
|
||||
_sql.Where(clause);
|
||||
_sql.Where(clause.Item1, clause.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -694,7 +694,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IEnumerable<IContent> result;
|
||||
var pagedResult = Database.Page<DocumentDto>(pageNumber, pageSize, modifiedSQL, sql.Arguments);
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
if (totalRecords > 0)
|
||||
//NOTE: We need to check the actual items returned, not the 'totalRecords', that is because if you request a page number
|
||||
// that doesn't actually have any data on it, the totalRecords will still indicate there are records but there are none in
|
||||
// the pageResult, then the GetAll will actually return ALL records in the db.
|
||||
if (pagedResult.Items.Any())
|
||||
{
|
||||
// Parse out node Ids and load content (we need the cast here in order to be able to call the IQueryable extension
|
||||
// methods OrderBy or OrderByDescending)
|
||||
|
||||
@@ -141,45 +141,59 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
foreach (var id in ids)
|
||||
return PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.id in (@ids)", new {ids = ids}));
|
||||
}
|
||||
else
|
||||
{
|
||||
return PerformGetAll(objectTypeId);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params Guid[] keys)
|
||||
{
|
||||
if (keys.Any())
|
||||
{
|
||||
return PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.uniqueID in (@keys)", new { keys = keys }));
|
||||
}
|
||||
else
|
||||
{
|
||||
return PerformGetAll(objectTypeId);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<IUmbracoEntity> PerformGetAll(Guid objectTypeId, Action<Sql> filter = null)
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, filter);
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
yield return Get(id, objectTypeId);
|
||||
yield return entity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, string.Empty);
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
if (isMedia)
|
||||
var dtos = _work.Database.Fetch<dynamic>(sql);
|
||||
foreach (var entity in dtos.Select(dto => factory.BuildEntityFromDynamic(dto)))
|
||||
{
|
||||
//for now treat media differently
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
yield return entity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var dtos = _work.Database.Fetch<dynamic>(sql);
|
||||
foreach (var entity in dtos.Select(dto => factory.BuildEntityFromDynamic(dto)))
|
||||
{
|
||||
yield return entity;
|
||||
}
|
||||
yield return entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query)
|
||||
{
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>) query).WhereClauses()));
|
||||
var sqlClause = GetBase(false, false, wheres);
|
||||
var sqlClause = GetBase(false, false, null);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(false, false));
|
||||
|
||||
@@ -193,12 +207,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId)
|
||||
{
|
||||
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>)query).WhereClauses()));
|
||||
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, wheres, objectTypeId);
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, null, objectTypeId);
|
||||
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var entitySql = translator.Translate();
|
||||
@@ -207,7 +220,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
var mediaSql = GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), wheres);
|
||||
var wheres = query.GetWhereClauses().ToArray();
|
||||
|
||||
var mediaSql = GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), sql =>
|
||||
{
|
||||
//adds the additional filters
|
||||
foreach (var whereClause in wheres)
|
||||
{
|
||||
sql.Where(whereClause.Item1, whereClause.Item2);
|
||||
}
|
||||
});
|
||||
|
||||
//treat media differently for now
|
||||
//TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields
|
||||
@@ -218,7 +240,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
else
|
||||
{
|
||||
//use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData
|
||||
var dtos = _work.Database.Fetch<dynamic>(entitySql.Append(GetGroupBy(isContent, false)));
|
||||
var finalSql = entitySql.Append(GetGroupBy(isContent, false));
|
||||
var dtos = _work.Database.Fetch<dynamic>(finalSql);
|
||||
return dtos.Select(factory.BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
||||
}
|
||||
}
|
||||
@@ -246,16 +269,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)));
|
||||
}
|
||||
|
||||
protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, string additionalWhereClause)
|
||||
protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, Action<Sql> filter)
|
||||
{
|
||||
var entitySql = GetBaseWhere(GetBase, isContent, isMedia, additionalWhereClause, objectTypeId);
|
||||
var entitySql = GetBaseWhere(GetBase, isContent, isMedia, filter, objectTypeId);
|
||||
|
||||
if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false));
|
||||
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)));
|
||||
return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), filter);
|
||||
}
|
||||
|
||||
private Sql GetFullSqlForMedia(Sql entitySql, string additionWhereStatement = "")
|
||||
private Sql GetFullSqlForMedia(Sql entitySql, Action<Sql> filter = null)
|
||||
{
|
||||
//this will add any dataNvarchar property to the output which can be added to the additional properties
|
||||
|
||||
@@ -268,7 +291,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On<PropertyTypeDto, PropertyDataDto>(dto => dto.Id, dto => dto.PropertyTypeId)
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(dto => dto.DataTypeId, dto => dto.DataTypeId)
|
||||
.Where("umbracoNode.nodeObjectType = @nodeObjectType" + additionWhereStatement, new {nodeObjectType = Constants.ObjectTypes.Media});
|
||||
.Where("umbracoNode.nodeObjectType = @nodeObjectType", new {nodeObjectType = Constants.ObjectTypes.Media});
|
||||
|
||||
if (filter != null)
|
||||
{
|
||||
filter(joinSql);
|
||||
}
|
||||
|
||||
//We're going to create a query to query against the entity SQL
|
||||
// because we cannot group by nText columns and we have a COUNT in the entitySql we cannot simply left join
|
||||
@@ -284,7 +312,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return wrappedSql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, string additionWhereStatement = "")
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, Action<Sql> customFilter)
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
@@ -316,10 +344,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
var entitySql = new Sql()
|
||||
.Select(columns.ToArray())
|
||||
.From("umbracoNode umbracoNode")
|
||||
.LeftJoin("umbracoNode parent").On("parent.parentID = umbracoNode.id");
|
||||
|
||||
|
||||
.From("umbracoNode umbracoNode");
|
||||
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
entitySql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id")
|
||||
@@ -332,43 +358,50 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On("umbracoNode.id = latest.nodeId");
|
||||
}
|
||||
|
||||
entitySql.LeftJoin("umbracoNode parent").On("parent.parentID = umbracoNode.id");
|
||||
|
||||
if (customFilter != null)
|
||||
{
|
||||
customFilter(entitySql);
|
||||
}
|
||||
|
||||
return entitySql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, string additionWhereStatement, Guid nodeObjectType)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, Action<Sql> filter, Guid nodeObjectType)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, additionWhereStatement)
|
||||
var sql = baseQuery(isContent, isMedia, filter)
|
||||
.Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = nodeObjectType });
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.id = @Id", new { Id = id })
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, Guid key)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, Guid key)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.uniqueID = '" + key + "'")
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.uniqueID = @UniqueID", new { UniqueID = key })
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new {Id = id, NodeObjectType = nodeObjectType});
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, Guid key)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, Guid key)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.uniqueID = '" + key + "'")
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.uniqueID = @UniqueID AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new { UniqueID = key, NodeObjectType = nodeObjectType });
|
||||
return sql;
|
||||
@@ -497,7 +530,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
// Add this UmbracoProperty to the current additional data
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
@@ -516,7 +549,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var prev = Current;
|
||||
|
||||
// Setup the new current UmbracoEntity
|
||||
|
||||
|
||||
Current = _factory.BuildEntityFromDynamic(a);
|
||||
|
||||
if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false)
|
||||
|
||||
@@ -203,13 +203,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//find the member by username
|
||||
var memberSql = new Sql();
|
||||
var memberObjectType = new Guid(Constants.ObjectTypes.Member);
|
||||
var escapedUsername = PetaPocoExtensions.EscapeAtSymbols(username);
|
||||
|
||||
memberSql.Select("umbracoNode.id")
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<MemberDto>()
|
||||
.On<NodeDto, MemberDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == memberObjectType)
|
||||
.Where<MemberDto>(x => x.LoginName == escapedUsername);
|
||||
.Where<MemberDto>(x => x.LoginName == username);
|
||||
var memberIdUsername = Database.Fetch<int?>(memberSql).FirstOrDefault();
|
||||
if (memberIdUsername.HasValue == false)
|
||||
{
|
||||
@@ -280,6 +280,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public void AssignRolesInternal(int[] memberIds, string[] roleNames)
|
||||
{
|
||||
//ensure they're unique
|
||||
memberIds = memberIds.Distinct().ToArray();
|
||||
|
||||
//create the missing roles first
|
||||
|
||||
var existingSql = new Sql()
|
||||
|
||||
@@ -529,10 +529,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public bool Exists(string username)
|
||||
{
|
||||
var sql = new Sql();
|
||||
var escapedUserName = PetaPocoExtensions.EscapeAtSymbols(username);
|
||||
|
||||
sql.Select("COUNT(*)")
|
||||
.From<MemberDto>()
|
||||
.Where<MemberDto>(x => x.LoginName == escapedUserName);
|
||||
.Where<MemberDto>(x => x.LoginName == username);
|
||||
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
//TODO: Consider caching implications.
|
||||
|
||||
//TODO: We need to add lookups for parentId or path! (i.e. get content in tag group that are descendants of x)
|
||||
|
||||
|
||||
public IEnumerable<TaggedEntity> GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string tagGroup)
|
||||
{
|
||||
@@ -285,7 +287,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (withGrouping)
|
||||
{
|
||||
sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags.[Group], Count(*) NodeCount");
|
||||
sql = sql.Select("cmsTags.Id, cmsTags.Tag, cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @", Count(*) NodeCount");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -315,7 +317,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
private Sql ApplyGroupByToTagsQuery(Sql sql)
|
||||
{
|
||||
return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags.[Group]" });
|
||||
return sql.GroupBy(new string[] { "cmsTags.Id", "cmsTags.Tag", "cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @"" });
|
||||
}
|
||||
|
||||
private IEnumerable<ITag> ExecuteTagsQuery(Sql sql)
|
||||
@@ -438,7 +440,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
" AND tagId IN ",
|
||||
"(SELECT id FROM cmsTags INNER JOIN ",
|
||||
tagSetSql,
|
||||
" ON (TagSet.Tag = cmsTags.Tag and TagSet.[Group] = cmsTags.[Group]))");
|
||||
" ON (TagSet.Tag = cmsTags.Tag and TagSet." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @" = cmsTags." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @"))");
|
||||
|
||||
Database.Execute(deleteSql);
|
||||
}
|
||||
@@ -484,9 +486,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
private static string GetTagSet(IEnumerable<ITag> tagsToInsert)
|
||||
{
|
||||
//TODO: Fix this query, since this is going to be basically a unique query each time, this will cause some mem usage in peta poco,
|
||||
// and surely there's a nicer way!
|
||||
//TODO: When we fix, be sure to remove the @ symbol escape
|
||||
|
||||
var array = tagsToInsert
|
||||
.Select(tag =>
|
||||
string.Format("select '{0}' as Tag, '{1}' as [Group]",
|
||||
string.Format("select '{0}' as Tag, '{1}' as " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Group") + @"",
|
||||
PetaPocoExtensions.EscapeAtSymbols(tag.Text.Replace("'", "''")), tag.Group))
|
||||
.ToArray();
|
||||
return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet";
|
||||
|
||||
@@ -261,10 +261,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public bool Exists(string username)
|
||||
{
|
||||
var sql = new Sql();
|
||||
var escapedUserName = PetaPocoExtensions.EscapeAtSymbols(username);
|
||||
|
||||
sql.Select("COUNT(*)")
|
||||
.From<UserDto>()
|
||||
.Where<UserDto>(x => x.UserName == escapedUserName);
|
||||
.Where<UserDto>(x => x.UserName == username);
|
||||
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
|
||||
@@ -230,6 +230,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="updateDate"></param>
|
||||
/// <returns></returns>
|
||||
protected PropertyCollection GetPropertyCollection(int id, Guid versionId, IContentTypeComposition contentType, DateTime createDate, DateTime updateDate)
|
||||
|
||||
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select("cmsPropertyData.*, cmsDataTypePreValues.id as preValId, cmsDataTypePreValues.value, cmsDataTypePreValues.sortorder, cmsDataTypePreValues.alias, cmsDataTypePreValues.datatypeNodeId")
|
||||
|
||||
@@ -13,10 +13,19 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
string EscapeString(string val);
|
||||
|
||||
string GetWildcardPlaceholder();
|
||||
string GetStringColumnEqualComparison(string column, int paramIndex, TextColumnType columnType);
|
||||
string GetStringColumnWildcardComparison(string column, int paramIndex, TextColumnType columnType);
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType);
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType);
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType);
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType);
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType);
|
||||
|
||||
string GetQuotedTableName(string tableName);
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class for defining MS sql implementations
|
||||
/// </summary>
|
||||
/// <typeparam name="TSyntax"></typeparam>
|
||||
public abstract class MicrosoftSqlSyntaxProviderBase<TSyntax> : SqlSyntaxProviderBase<TSyntax>
|
||||
where TSyntax : ISqlSyntaxProvider
|
||||
{
|
||||
public override string RenameTable { get { return "sp_rename '{0}', '{1}'"; } }
|
||||
|
||||
public override string AddColumn { get { return "ALTER TABLE {0} ADD {1}"; } }
|
||||
|
||||
public override string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("[{0}]", tableName);
|
||||
}
|
||||
|
||||
public override string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("[{0}]", columnName);
|
||||
}
|
||||
|
||||
public override string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("[{0}]", name);
|
||||
}
|
||||
|
||||
public override string GetStringColumnEqualComparison(string column, int paramIndex, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnEqualComparison(column, paramIndex, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for = comparison with NText columns but allows this syntax
|
||||
return string.Format("{0} LIKE @{1}", column, paramIndex);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnWildcardComparison(string column, int paramIndex, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnWildcardComparison(column, paramIndex, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE @{1}", column, paramIndex);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public override string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnStartsWithComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '{1}%'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public override string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnEndsWithComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '%{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public override string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnContainsComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '%{1}%'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnContainsComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
/// Represents an SqlSyntaxProvider for Sql Ce
|
||||
/// </summary>
|
||||
[SqlSyntaxProviderAttribute("System.Data.SqlServerCe.4.0")]
|
||||
public class SqlCeSyntaxProvider : SqlSyntaxProviderBase<SqlCeSyntaxProvider>
|
||||
public class SqlCeSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlCeSyntaxProvider>
|
||||
{
|
||||
public SqlCeSyntaxProvider()
|
||||
{
|
||||
@@ -60,6 +60,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
return indexType;
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public override string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
@@ -74,76 +75,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnStartsWithComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '{1}%'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnEndsWithComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '%{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnContainsComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '%{1}%'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnContainsComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("[{0}]", tableName);
|
||||
}
|
||||
|
||||
public override string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("[{0}]", columnName);
|
||||
}
|
||||
|
||||
public override string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("[{0}]", name);
|
||||
}
|
||||
|
||||
|
||||
public override string FormatColumnRename(string tableName, string oldName, string newName)
|
||||
{
|
||||
@@ -285,10 +217,10 @@ ORDER BY TABLE_NAME, INDEX_NAME");
|
||||
}
|
||||
}
|
||||
|
||||
public override string AddColumn { get { return "ALTER TABLE {0} ADD {1}"; } }
|
||||
|
||||
|
||||
public override string DropIndex { get { return "DROP INDEX {1}.{0}"; } }
|
||||
|
||||
public override string RenameTable { get { return "sp_rename '{0}', '{1}'"; } }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
@@ -10,7 +9,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
/// Represents an SqlSyntaxProvider for Sql Server
|
||||
/// </summary>
|
||||
[SqlSyntaxProviderAttribute("System.Data.SqlClient")]
|
||||
public class SqlServerSyntaxProvider : SqlSyntaxProviderBase<SqlServerSyntaxProvider>
|
||||
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
|
||||
{
|
||||
public SqlServerSyntaxProvider()
|
||||
{
|
||||
@@ -33,91 +32,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
/// Gets/sets the version of the current SQL server instance
|
||||
/// </summary>
|
||||
internal Lazy<SqlServerVersionName> VersionName { get; set; }
|
||||
|
||||
public override string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnEqualComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for = comparison with NText columns but allows this syntax
|
||||
return string.Format("{0} LIKE '{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnStartsWithComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '{1}%'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnEndsWithComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '%{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnContainsComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '%{1}%'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
switch (columnType)
|
||||
{
|
||||
case TextColumnType.NVarchar:
|
||||
return base.GetStringColumnContainsComparison(column, value, columnType);
|
||||
case TextColumnType.NText:
|
||||
//MSSQL doesn't allow for upper methods with NText columns
|
||||
return string.Format("{0} LIKE '{1}'", column, value);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("columnType");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("[{0}]", tableName);
|
||||
}
|
||||
|
||||
public override string GetQuotedColumnName(string columnName)
|
||||
{
|
||||
return string.Format("[{0}]", columnName);
|
||||
}
|
||||
|
||||
public override string GetQuotedName(string name)
|
||||
{
|
||||
return string.Format("[{0}]", name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override IEnumerable<string> GetTablesInSchema(Database db)
|
||||
{
|
||||
@@ -218,12 +134,11 @@ order by T.name, I.name");
|
||||
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
|
||||
}
|
||||
|
||||
public override string AddColumn { get { return "ALTER TABLE {0} ADD {1}"; } }
|
||||
|
||||
|
||||
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
|
||||
|
||||
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
|
||||
|
||||
public override string RenameTable { get { return "sp_rename '{0}', '{1}'"; } }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
};
|
||||
}
|
||||
|
||||
public string GetWildcardPlaceholder()
|
||||
{
|
||||
return "%";
|
||||
}
|
||||
|
||||
public string StringLengthNonUnicodeColumnDefinitionFormat = "VARCHAR({0})";
|
||||
public string StringLengthUnicodeColumnDefinitionFormat = "NVARCHAR({0})";
|
||||
|
||||
@@ -108,34 +113,51 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
return PetaPocoExtensions.EscapeAtSymbols(val.Replace("'", "''"));
|
||||
}
|
||||
|
||||
public virtual string GetStringColumnEqualComparison(string column, int paramIndex, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) = upper(@{1})", column, paramIndex);
|
||||
}
|
||||
|
||||
public virtual string GetStringColumnWildcardComparison(string column, int paramIndex, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) LIKE upper(@{1})", column, paramIndex);
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public virtual string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) = '{1}'", column, value.ToUpper());
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public virtual string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) like '{1}%'", column, value.ToUpper());
|
||||
return string.Format("upper({0}) LIKE '{1}%'", column, value.ToUpper());
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public virtual string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) like '%{1}'", column, value.ToUpper());
|
||||
return string.Format("upper({0}) LIKE '%{1}'", column, value.ToUpper());
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public virtual string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) like '%{1}%'", column, value.ToUpper());
|
||||
return string.Format("upper({0}) LIKE '%{1}%'", column, value.ToUpper());
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload with the parameter index instead")]
|
||||
public virtual string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
|
||||
{
|
||||
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
|
||||
return string.Format("upper({0}) like '{1}'", column, value.ToUpper());
|
||||
return string.Format("upper({0}) LIKE '{1}'", column, value.ToUpper());
|
||||
}
|
||||
|
||||
public virtual string GetQuotedTableName(string tableName)
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
/// <remarks>
|
||||
/// See: http://issues.umbraco.org/issue/U4-3876
|
||||
/// </remarks>
|
||||
public static string GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery)
|
||||
public static Sql GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery)
|
||||
{
|
||||
return string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)",
|
||||
sqlProvider.GetQuotedTableName(tableName),
|
||||
sqlProvider.GetQuotedColumnName(columnName),
|
||||
subQuery.SQL);
|
||||
return new Sql(string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)",
|
||||
sqlProvider.GetQuotedTableName(tableName),
|
||||
sqlProvider.GetQuotedColumnName(columnName),
|
||||
subQuery.SQL), subQuery.Arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Cache;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -15,15 +16,18 @@ namespace Umbraco.Core.Services
|
||||
internal class ApplicationTreeService : IApplicationTreeService
|
||||
{
|
||||
private readonly CacheHelper _cache;
|
||||
private IEnumerable<ApplicationTree> _allAvailableTrees;
|
||||
private volatile bool _isInitialized = false;
|
||||
internal const string TreeConfigFileName = "trees.config";
|
||||
private static string _treeConfig;
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
public ApplicationTreeService(CacheHelper cache)
|
||||
{
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
internal const string TreeConfigFileName = "trees.config";
|
||||
private static string _treeConfig;
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// gets/sets the trees.config file path
|
||||
@@ -45,74 +49,101 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The cache storage for all application trees
|
||||
/// The main entry point to get application trees
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This lazily on first access will scan for plugin trees and ensure the trees.config is up-to-date with the plugins. If plugins
|
||||
/// haven't changed on disk then the file will not be saved. The trees are all then loaded from this config file into cache and returned.
|
||||
/// </remarks>
|
||||
private List<ApplicationTree> GetAppTrees()
|
||||
{
|
||||
return _cache.GetCacheItem(
|
||||
return _cache.RuntimeCache.GetCacheItem<List<ApplicationTree>>(
|
||||
CacheKeys.ApplicationTreeCacheKey,
|
||||
() =>
|
||||
{
|
||||
var list = ReadFromXmlAndSort();
|
||||
|
||||
//On first access we need to do some initialization
|
||||
if (_isInitialized == false)
|
||||
{
|
||||
var list = new List<ApplicationTree>();
|
||||
|
||||
LoadXml(doc =>
|
||||
lock (Locker)
|
||||
{
|
||||
if (_isInitialized == false)
|
||||
{
|
||||
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
|
||||
{
|
||||
var sortOrderAttr = x.Attribute("sortOrder");
|
||||
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
|
||||
}))
|
||||
//now we can check the non-volatile flag
|
||||
if (_allAvailableTrees != null)
|
||||
{
|
||||
var applicationAlias = (string) addElement.Attribute("application");
|
||||
var type = (string) addElement.Attribute("type");
|
||||
var assembly = (string) addElement.Attribute("assembly");
|
||||
var hasChanges = false;
|
||||
|
||||
var clrType = Type.GetType(type);
|
||||
if (clrType == null)
|
||||
LoadXml(doc =>
|
||||
{
|
||||
LogHelper.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
|
||||
continue;
|
||||
}
|
||||
//Now, load in the xml structure and update it with anything that is not declared there and save the file.
|
||||
|
||||
//check if the tree definition (applicationAlias + type + assembly) is already in the list
|
||||
//NOTE: On the first iteration here, it will lazily scan all trees, etc... this is because this ienumerable is lazy
|
||||
// based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this
|
||||
// currently because of the legacy assemblies and types not in the Core.
|
||||
|
||||
if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false)
|
||||
//Get all the trees not registered in the config
|
||||
var unregistered = _allAvailableTrees
|
||||
.Where(x => list.Any(l => l.Alias == x.Alias) == false)
|
||||
.ToArray();
|
||||
|
||||
hasChanges = unregistered.Any();
|
||||
|
||||
if (hasChanges == false) return false;
|
||||
|
||||
//add the unregistered ones to the list and re-save the file if any changes were found
|
||||
var count = 0;
|
||||
foreach (var tree in unregistered)
|
||||
{
|
||||
doc.Root.Add(new XElement("add",
|
||||
new XAttribute("initialize", tree.Initialize),
|
||||
new XAttribute("sortOrder", tree.SortOrder),
|
||||
new XAttribute("alias", tree.Alias),
|
||||
new XAttribute("application", tree.ApplicationAlias),
|
||||
new XAttribute("title", tree.Title),
|
||||
new XAttribute("iconClosed", tree.IconClosed),
|
||||
new XAttribute("iconOpen", tree.IconOpened),
|
||||
new XAttribute("type", tree.Type)));
|
||||
count++;
|
||||
}
|
||||
|
||||
//don't save if there's no changes
|
||||
return count > 0;
|
||||
}, true);
|
||||
|
||||
if (hasChanges)
|
||||
{
|
||||
list.Add(new ApplicationTree(
|
||||
addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value),
|
||||
addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte) 0,
|
||||
addElement.Attribute("application").Value,
|
||||
addElement.Attribute("alias").Value,
|
||||
addElement.Attribute("title").Value,
|
||||
addElement.Attribute("iconClosed").Value,
|
||||
addElement.Attribute("iconOpen").Value,
|
||||
addElement.Attribute("type").Value));
|
||||
//If there were changes, we need to re-read the structures from the XML
|
||||
list = ReadFromXmlAndSort();
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
return list;
|
||||
});
|
||||
_isInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void Intitialize(IEnumerable<ApplicationTree> existingTrees)
|
||||
/// <summary>
|
||||
/// Initializes the service with any trees found in plugins
|
||||
/// </summary>
|
||||
/// <param name="allAvailableTrees">
|
||||
/// A collection of all available tree found in assemblies in the application
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This will update the trees.config with the found tree plugins that are not currently listed in the file when the first
|
||||
/// access is made to resolve the tree collection
|
||||
/// </remarks>
|
||||
public void Intitialize(IEnumerable<ApplicationTree> allAvailableTrees)
|
||||
{
|
||||
LoadXml(doc =>
|
||||
{
|
||||
foreach (var tree in existingTrees)
|
||||
{
|
||||
doc.Root.Add(new XElement("add",
|
||||
new XAttribute("initialize", tree.Initialize),
|
||||
new XAttribute("sortOrder", tree.SortOrder),
|
||||
new XAttribute("alias", tree.Alias),
|
||||
new XAttribute("application", tree.ApplicationAlias),
|
||||
new XAttribute("title", tree.Title),
|
||||
new XAttribute("iconClosed", tree.IconClosed),
|
||||
new XAttribute("iconOpen", tree.IconOpened),
|
||||
new XAttribute("type", tree.Type)));
|
||||
}
|
||||
|
||||
}, true);
|
||||
_allAvailableTrees = allAvailableTrees;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -134,16 +165,19 @@ namespace Umbraco.Core.Services
|
||||
|
||||
if (el == null)
|
||||
{
|
||||
doc.Root.Add(new XElement("add",
|
||||
new XAttribute("initialize", initialize),
|
||||
new XAttribute("sortOrder", sortOrder),
|
||||
new XAttribute("alias", alias),
|
||||
new XAttribute("application", applicationAlias),
|
||||
new XAttribute("title", title),
|
||||
new XAttribute("iconClosed", iconClosed),
|
||||
new XAttribute("iconOpen", iconOpened),
|
||||
new XAttribute("type", type)));
|
||||
doc.Root.Add(new XElement("add",
|
||||
new XAttribute("initialize", initialize),
|
||||
new XAttribute("sortOrder", sortOrder),
|
||||
new XAttribute("alias", alias),
|
||||
new XAttribute("application", applicationAlias),
|
||||
new XAttribute("title", title),
|
||||
new XAttribute("iconClosed", iconClosed),
|
||||
new XAttribute("iconOpen", iconOpened),
|
||||
new XAttribute("type", type)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}, true);
|
||||
|
||||
OnNew(new ApplicationTree(initialize, sortOrder, applicationAlias, alias, title, iconClosed, iconOpened, type), new EventArgs());
|
||||
@@ -161,7 +195,7 @@ namespace Umbraco.Core.Services
|
||||
if (el != null)
|
||||
{
|
||||
el.RemoveAttributes();
|
||||
|
||||
|
||||
el.Add(new XAttribute("initialize", tree.Initialize));
|
||||
el.Add(new XAttribute("sortOrder", tree.SortOrder));
|
||||
el.Add(new XAttribute("alias", tree.Alias));
|
||||
@@ -172,6 +206,8 @@ namespace Umbraco.Core.Services
|
||||
el.Add(new XAttribute("type", tree.Type));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}, true);
|
||||
|
||||
OnUpdated(tree, new EventArgs());
|
||||
@@ -181,11 +217,16 @@ namespace Umbraco.Core.Services
|
||||
/// Deletes this instance.
|
||||
/// </summary>
|
||||
public void DeleteTree(ApplicationTree tree)
|
||||
{
|
||||
{
|
||||
LoadXml(doc =>
|
||||
{
|
||||
doc.Root.Elements("add").Where(x => x.Attribute("application") != null && x.Attribute("application").Value == tree.ApplicationAlias &&
|
||||
x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove();
|
||||
doc.Root.Elements("add")
|
||||
.Where(x => x.Attribute("application") != null
|
||||
&& x.Attribute("application").Value == tree.ApplicationAlias
|
||||
&& x.Attribute("alias") != null && x.Attribute("alias").Value == tree.Alias).Remove();
|
||||
|
||||
return true;
|
||||
|
||||
}, true);
|
||||
|
||||
OnDeleted(tree, new EventArgs());
|
||||
@@ -231,31 +272,44 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var list = GetAppTrees().FindAll(
|
||||
t =>
|
||||
{
|
||||
if (onlyInitialized)
|
||||
return (t.ApplicationAlias == applicationAlias && t.Initialize);
|
||||
return (t.ApplicationAlias == applicationAlias);
|
||||
}
|
||||
{
|
||||
if (onlyInitialized)
|
||||
return (t.ApplicationAlias == applicationAlias && t.Initialize);
|
||||
return (t.ApplicationAlias == applicationAlias);
|
||||
}
|
||||
);
|
||||
|
||||
return list.OrderBy(x => x.SortOrder).ToArray();
|
||||
}
|
||||
|
||||
internal void LoadXml(Action<XDocument> callback, bool saveAfterCallback)
|
||||
/// <summary>
|
||||
/// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the
|
||||
/// callback with the xml document and saves the structure back to disk if saveAfterCallback is true.
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="saveAfterCallbackIfChanges"></param>
|
||||
internal void LoadXml(Func<XDocument, bool> callback, bool saveAfterCallbackIfChanges)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
var doc = File.Exists(TreeConfigFilePath)
|
||||
? XDocument.Load(TreeConfigFilePath)
|
||||
: XDocument.Parse("<?xml version=\"1.0\"?><trees />");
|
||||
|
||||
if (doc.Root != null)
|
||||
{
|
||||
callback.Invoke(doc);
|
||||
var hasChanges = callback.Invoke(doc);
|
||||
|
||||
if (saveAfterCallback)
|
||||
if (saveAfterCallbackIfChanges && hasChanges
|
||||
//Don't save it if it is empty, in some very rare cases if the app domain get's killed in the middle of this process
|
||||
// in some insane way the file saved will be empty. I'm pretty sure it's not actually anything to do with the xml doc and
|
||||
// more about the IO trying to save the XML doc, but it doesn't hurt to check.
|
||||
&& doc.Root != null && doc.Root.Elements().Any())
|
||||
{
|
||||
//ensures the folder exists
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(TreeConfigFilePath));
|
||||
|
||||
//saves it
|
||||
doc.Save(TreeConfigFilePath);
|
||||
|
||||
//remove the cache now that it has changed SD: I'm leaving this here even though it
|
||||
@@ -266,6 +320,54 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
private List<ApplicationTree> ReadFromXmlAndSort()
|
||||
{
|
||||
var list = new List<ApplicationTree>();
|
||||
|
||||
//read in the xml file containing trees and convert them all to ApplicationTree instances
|
||||
LoadXml(doc =>
|
||||
{
|
||||
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
|
||||
{
|
||||
var sortOrderAttr = x.Attribute("sortOrder");
|
||||
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
|
||||
}))
|
||||
{
|
||||
var applicationAlias = (string)addElement.Attribute("application");
|
||||
var type = (string)addElement.Attribute("type");
|
||||
var assembly = (string)addElement.Attribute("assembly");
|
||||
|
||||
var clrType = Type.GetType(type);
|
||||
if (clrType == null)
|
||||
{
|
||||
LogHelper.Warn<ApplicationTreeService>("The tree definition: " + addElement.ToString() + " could not be resolved to a .Net object type");
|
||||
continue;
|
||||
}
|
||||
|
||||
//check if the tree definition (applicationAlias + type + assembly) is already in the list
|
||||
|
||||
if (list.Any(tree => tree.ApplicationAlias.InvariantEquals(applicationAlias) && tree.GetRuntimeType() == clrType) == false)
|
||||
{
|
||||
list.Add(new ApplicationTree(
|
||||
addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value),
|
||||
addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte)0,
|
||||
addElement.Attribute("application").Value,
|
||||
addElement.Attribute("alias").Value,
|
||||
addElement.Attribute("title").Value,
|
||||
addElement.Attribute("iconClosed").Value,
|
||||
addElement.Attribute("iconOpen").Value,
|
||||
addElement.Attribute("type").Value));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}, false);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
internal static event TypedEventHandler<ApplicationTree, EventArgs> Deleted;
|
||||
private static void OnDeleted(ApplicationTree app, EventArgs args)
|
||||
{
|
||||
|
||||
@@ -520,6 +520,10 @@ namespace Umbraco.Core.Services
|
||||
public IEnumerable<IContent> GetDescendants(int id)
|
||||
{
|
||||
var content = GetById(id);
|
||||
if (content == null)
|
||||
{
|
||||
return Enumerable.Empty<IContent>();
|
||||
}
|
||||
return GetDescendants(content);
|
||||
}
|
||||
|
||||
@@ -532,7 +536,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith(content.Path) && x.Id != content.Id);
|
||||
var pathMatch = content.Path + ",";
|
||||
var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != content.Id);
|
||||
var contents = repository.GetByQuery(query);
|
||||
|
||||
return contents;
|
||||
|
||||
@@ -252,7 +252,8 @@ namespace Umbraco.Core.Services
|
||||
using (var repository = _repositoryFactory.CreateEntityRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var entity = repository.Get(id);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id);
|
||||
var pathMatch = entity.Path + ",";
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id);
|
||||
var entities = repository.GetByQuery(query);
|
||||
|
||||
return entities;
|
||||
|
||||
@@ -248,7 +248,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var tab = new XElement("Tab",
|
||||
new XElement("Id", propertyGroup.Id.ToString(CultureInfo.InvariantCulture)),
|
||||
new XElement("Caption", propertyGroup.Name));
|
||||
new XElement("Caption", propertyGroup.Name),
|
||||
new XElement("SortOrder", propertyGroup.SortOrder));
|
||||
|
||||
tabs.Add(tab);
|
||||
}
|
||||
|
||||
@@ -354,7 +356,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var tab = new XElement("Tab",
|
||||
new XElement("Id", propertyGroup.Id.ToString(CultureInfo.InvariantCulture)),
|
||||
new XElement("Caption", propertyGroup.Name));
|
||||
new XElement("Caption", propertyGroup.Name),
|
||||
new XElement("SortOrder", propertyGroup.SortOrder));
|
||||
tabs.Add(tab);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,17 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IApplicationTreeService
|
||||
{
|
||||
void Intitialize(IEnumerable<ApplicationTree> existingTrees);
|
||||
/// <summary>
|
||||
/// Initializes the service with any trees found in plugins
|
||||
/// </summary>
|
||||
/// <param name="allAvailableTrees">
|
||||
/// A collection of all available tree found in assemblies in the application
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This will update the trees.config with the found tree plugins that are not currently listed in the file when the first
|
||||
/// access is made to resolve the tree collection
|
||||
/// </remarks>
|
||||
void Intitialize(IEnumerable<ApplicationTree> allAvailableTrees);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new application tree.
|
||||
|
||||
@@ -6,10 +6,15 @@ namespace Umbraco.Core.Services
|
||||
public interface ISectionService
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures all available sections exist in the storage medium
|
||||
/// Initializes the service with all available application plugins
|
||||
/// </summary>
|
||||
/// <param name="existingSections"></param>
|
||||
void Initialize(IEnumerable<Section> existingSections);
|
||||
/// <param name="allAvailableSections">
|
||||
/// All application plugins found in assemblies
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This is used to populate the app.config file with any applications declared in plugins that don't exist in the file
|
||||
/// </remarks>
|
||||
void Initialize(IEnumerable<Section> allAvailableSections);
|
||||
|
||||
/// <summary>
|
||||
/// The cache storage for all applications
|
||||
|
||||
@@ -402,6 +402,10 @@ namespace Umbraco.Core.Services
|
||||
public IEnumerable<IMedia> GetDescendants(int id)
|
||||
{
|
||||
var media = GetById(id);
|
||||
if (media == null)
|
||||
{
|
||||
return Enumerable.Empty<IMedia>();
|
||||
}
|
||||
return GetDescendants(media);
|
||||
}
|
||||
|
||||
@@ -415,7 +419,8 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Path.StartsWith(media.Path) && x.Id != media.Id);
|
||||
var pathMatch = media.Path + ",";
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != media.Id);
|
||||
var medias = repository.GetByQuery(query);
|
||||
|
||||
return medias;
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Umbraco.Core.Services
|
||||
public XElement Export(IContent content, bool deep = false, bool raiseEvents = true)
|
||||
{
|
||||
var nodeName = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema ? "node" : content.ContentType.Alias.ToSafeAliasWithForcingCheck();
|
||||
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (ExportingContent.IsRaisedEventCancelled(new ExportEventArgs<IContent>(content, nodeName), this))
|
||||
@@ -84,13 +84,13 @@ namespace Umbraco.Core.Services
|
||||
var exporter = new EntityXmlSerializer();
|
||||
var xml = exporter.Serialize(_contentService, _dataTypeService, content, deep);
|
||||
|
||||
if(raiseEvents)
|
||||
if (raiseEvents)
|
||||
ExportedContent.RaiseEvent(new ExportEventArgs<IContent>(content, xml, false), this);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Imports and saves package xml as <see cref="IContent"/>
|
||||
@@ -107,7 +107,7 @@ namespace Umbraco.Core.Services
|
||||
if (ImportingContent.IsRaisedEventCancelled(new ImportEventArgs<IContent>(element), this))
|
||||
return Enumerable.Empty<IContent>();
|
||||
}
|
||||
|
||||
|
||||
var name = element.Name.LocalName;
|
||||
if (name.Equals("DocumentSet"))
|
||||
{
|
||||
@@ -120,7 +120,7 @@ namespace Umbraco.Core.Services
|
||||
if (contents.Any())
|
||||
_contentService.Save(contents, userId);
|
||||
|
||||
if(raiseEvents)
|
||||
if (raiseEvents)
|
||||
ImportedContent.RaiseEvent(new ImportEventArgs<IContent>(contents, element, false), this);
|
||||
return contents;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Services
|
||||
if (contents.Any())
|
||||
_contentService.Save(contents, userId);
|
||||
|
||||
if(raiseEvents)
|
||||
if (raiseEvents)
|
||||
ImportedContent.RaiseEvent(new ImportEventArgs<IContent>(contents, element, false), this);
|
||||
return contents;
|
||||
}
|
||||
@@ -248,7 +248,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
//TODO: We need to refactor this so the packager isn't making direct db calls for an 'edge' case
|
||||
var database = ApplicationContext.Current.DatabaseContext.Database;
|
||||
var dtos = database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new {Id = propertyType.DataTypeDefinitionId});
|
||||
var dtos = database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = propertyType.DataTypeDefinitionId });
|
||||
|
||||
var propertyValueList = new List<string>();
|
||||
foreach (var preValue in propertyValue.Split(','))
|
||||
@@ -261,7 +261,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
//set property value
|
||||
content.SetValue(propertyTypeAlias, propertyValue);
|
||||
content.SetValue(propertyTypeAlias, propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -491,13 +491,13 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
contentType.AddPropertyGroup(caption);
|
||||
|
||||
int sortOrder;
|
||||
if(tab.Element("SortOrder") != null &&
|
||||
int.TryParse(tab.Element("SortOrder").Value, out sortOrder))
|
||||
{
|
||||
// Override the sort order with the imported value
|
||||
contentType.PropertyGroups[caption].SortOrder = sortOrder;
|
||||
}
|
||||
}
|
||||
|
||||
int sortOrder;
|
||||
if (tab.Element("SortOrder") != null && int.TryParse(tab.Element("SortOrder").Value, out sortOrder))
|
||||
{
|
||||
// Override the sort order with the imported value
|
||||
contentType.PropertyGroups[caption].SortOrder = sortOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,7 +549,7 @@ namespace Umbraco.Core.Services
|
||||
dataTypeDefinition = dataTypeDefinitions.First();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For backwards compatibility, if no datatype with that ID can be found, we're letting this fail silently.
|
||||
// This means that the property will not be created.
|
||||
if (dataTypeDefinition == null)
|
||||
@@ -786,15 +786,15 @@ namespace Umbraco.Core.Services
|
||||
var dataTypeDefinition = dataTypes.First(x => x.Name == dataTypeDefinitionName);
|
||||
|
||||
var valuesWithoutKeys = prevaluesElement.Elements("PreValue")
|
||||
.Where(x => ((string) x.Attribute("Alias")).IsNullOrWhiteSpace())
|
||||
.Where(x => ((string)x.Attribute("Alias")).IsNullOrWhiteSpace())
|
||||
.Select(x => x.Attribute("Value").Value);
|
||||
|
||||
var valuesWithKeys = prevaluesElement.Elements("PreValue")
|
||||
.Where(x => ((string) x.Attribute("Alias")).IsNullOrWhiteSpace() == false)
|
||||
.Where(x => ((string)x.Attribute("Alias")).IsNullOrWhiteSpace() == false)
|
||||
.ToDictionary(
|
||||
key => (string) key.Attribute("Alias"),
|
||||
val => new PreValue((string) val.Attribute("Value")));
|
||||
|
||||
key => (string)key.Attribute("Alias"),
|
||||
val => new PreValue((string)val.Attribute("Value")));
|
||||
|
||||
//save the values with keys
|
||||
_dataTypeService.SavePreValues(dataTypeDefinition, valuesWithKeys);
|
||||
|
||||
@@ -841,7 +841,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var exporter = new EntityXmlSerializer();
|
||||
var xml = exporter.Serialize(dictionaryItem);
|
||||
|
||||
|
||||
if (includeChildren)
|
||||
{
|
||||
var children = _localizationService.GetDictionaryItemChildren(dictionaryItem.Key);
|
||||
@@ -1115,7 +1115,7 @@ namespace Umbraco.Core.Services
|
||||
dontRender = bool.Parse(dontRenderElement.Value);
|
||||
}
|
||||
|
||||
var existingMacro = _macroService.GetByAlias(macroAlias) as Macro;
|
||||
var existingMacro = _macroService.GetByAlias(macroAlias) as Macro;
|
||||
var macro = existingMacro ?? new Macro(macroAlias, macroName, controlType, controlAssembly, xsltPath, scriptPath,
|
||||
cacheByPage, cacheByMember, dontRender, useInEditor, cacheDuration);
|
||||
|
||||
@@ -1210,7 +1210,7 @@ namespace Umbraco.Core.Services
|
||||
public XElement Export(IMedia media, bool deep = false, bool raiseEvents = true)
|
||||
{
|
||||
var nodeName = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema ? "node" : media.ContentType.Alias.ToSafeAliasWithForcingCheck();
|
||||
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (ExportingMedia.IsRaisedEventCancelled(new ExportEventArgs<IMedia>(media, nodeName), this))
|
||||
@@ -1220,7 +1220,7 @@ namespace Umbraco.Core.Services
|
||||
var exporter = new EntityXmlSerializer();
|
||||
var xml = exporter.Serialize(_mediaService, _dataTypeService, media, deep);
|
||||
|
||||
if(raiseEvents)
|
||||
if (raiseEvents)
|
||||
ExportedMedia.RaiseEvent(new ExportEventArgs<IMedia>(media, xml, false), this);
|
||||
|
||||
return xml;
|
||||
@@ -1334,7 +1334,7 @@ namespace Umbraco.Core.Services
|
||||
if (templates.Any())
|
||||
_fileService.SaveTemplate(templates, userId);
|
||||
|
||||
if(raiseEvents)
|
||||
if (raiseEvents)
|
||||
ImportedTemplate.RaiseEvent(new ImportEventArgs<ITemplate>(templates, element, false), this);
|
||||
|
||||
return templates;
|
||||
@@ -1352,10 +1352,10 @@ namespace Umbraco.Core.Services
|
||||
|
||||
IEnumerable<IFile> styleSheets = Enumerable.Empty<IFile>();
|
||||
|
||||
if(element.Elements().Any())
|
||||
if (element.Elements().Any())
|
||||
throw new NotImplementedException("This needs to be implimentet");
|
||||
|
||||
|
||||
|
||||
if (raiseEvents)
|
||||
ImportingStylesheets.RaiseEvent(new ImportEventArgs<IFile>(styleSheets, element, false), this);
|
||||
|
||||
@@ -1480,7 +1480,7 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IPackagingService, ImportEventArgs<IContent>> ImportedContent;
|
||||
|
||||
|
||||
|
||||
public static event TypedEventHandler<IPackagingService, ExportEventArgs<IContent>> ExportingContent;
|
||||
|
||||
/// <summary>
|
||||
@@ -1607,7 +1607,7 @@ namespace Umbraco.Core.Services
|
||||
/// Occurs before Importing Stylesheets
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IPackagingService, ImportEventArgs<IFile>> ImportingStylesheets;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Template is Imported and Saved
|
||||
/// </summary>
|
||||
@@ -1622,7 +1622,7 @@ namespace Umbraco.Core.Services
|
||||
/// Occurs after Template is Exported to Xml
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IPackagingService, ExportEventArgs<ITemplate>> ExportedTemplate;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Importing umbraco package
|
||||
/// </summary>
|
||||
|
||||
@@ -17,12 +17,19 @@ namespace Umbraco.Core.Services
|
||||
internal class SectionService : ISectionService
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private IEnumerable<Section> _allAvailableSections;
|
||||
private readonly IApplicationTreeService _applicationTreeService;
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
private readonly CacheHelper _cache;
|
||||
internal const string AppConfigFileName = "applications.config";
|
||||
private static string _appConfig;
|
||||
private volatile bool _isInitialized = false;
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
public SectionService(
|
||||
IUserService userService,
|
||||
IApplicationTreeService applicationTreeService,
|
||||
IApplicationTreeService applicationTreeService,
|
||||
IDatabaseUnitOfWorkProvider uowProvider,
|
||||
CacheHelper cache)
|
||||
{
|
||||
if (applicationTreeService == null) throw new ArgumentNullException("applicationTreeService");
|
||||
@@ -30,12 +37,11 @@ namespace Umbraco.Core.Services
|
||||
|
||||
_userService = userService;
|
||||
_applicationTreeService = applicationTreeService;
|
||||
_uowProvider = uowProvider;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
internal const string AppConfigFileName = "applications.config";
|
||||
private static string _appConfig;
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// gets/sets the application.config file path
|
||||
@@ -57,22 +63,17 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures all available sections exist in the storage medium
|
||||
/// Initializes the service with all available application plugins
|
||||
/// </summary>
|
||||
/// <param name="existingSections"></param>
|
||||
public void Initialize(IEnumerable<Section> existingSections)
|
||||
/// <param name="allAvailableSections">
|
||||
/// All application plugins found in assemblies
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This is used to populate the app.config file with any applications declared in plugins that don't exist in the file
|
||||
/// </remarks>
|
||||
public void Initialize(IEnumerable<Section> allAvailableSections)
|
||||
{
|
||||
LoadXml(doc =>
|
||||
{
|
||||
foreach (var attr in existingSections)
|
||||
{
|
||||
doc.Root.Add(new XElement("add",
|
||||
new XAttribute("alias", attr.Alias),
|
||||
new XAttribute("name", attr.Name),
|
||||
new XAttribute("icon", attr.Icon),
|
||||
new XAttribute("sortOrder", attr.SortOrder)));
|
||||
}
|
||||
}, true);
|
||||
_allAvailableSections = allAvailableSections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -80,7 +81,7 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public IEnumerable<Section> GetSections()
|
||||
{
|
||||
return _cache.GetCacheItem(
|
||||
return _cache.RuntimeCache.GetCacheItem<IEnumerable<Section>>(
|
||||
CacheKeys.ApplicationsCacheKey,
|
||||
() =>
|
||||
{
|
||||
@@ -88,28 +89,66 @@ namespace Umbraco.Core.Services
|
||||
//if (_testApps != null)
|
||||
// return _testApps;
|
||||
|
||||
var tmp = new List<Section>();
|
||||
var list = ReadFromXmlAndSort();
|
||||
|
||||
LoadXml(doc =>
|
||||
//On first access we need to do some initialization
|
||||
if (_isInitialized == false)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
|
||||
{
|
||||
var sortOrderAttr = x.Attribute("sortOrder");
|
||||
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
|
||||
}))
|
||||
if (_isInitialized == false)
|
||||
{
|
||||
var sortOrderAttr = addElement.Attribute("sortOrder");
|
||||
tmp.Add(new Section(addElement.Attribute("name").Value,
|
||||
addElement.Attribute("alias").Value,
|
||||
addElement.Attribute("icon").Value,
|
||||
sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0));
|
||||
//now we can check the non-volatile flag
|
||||
if (_allAvailableSections != null)
|
||||
{
|
||||
var hasChanges = false;
|
||||
|
||||
LoadXml(doc =>
|
||||
{
|
||||
//Now, load in the xml structure and update it with anything that is not declared there and save the file.
|
||||
|
||||
//NOTE: On the first iteration here, it will lazily scan all apps, etc... this is because this ienumerable is lazy
|
||||
// based on the ApplicationRegistrar - and as noted there this is not an ideal way to do things but were stuck like this
|
||||
// currently because of the legacy assemblies and types not in the Core.
|
||||
|
||||
//Get all the trees not registered in the config
|
||||
var unregistered = _allAvailableSections
|
||||
.Where(x => list.Any(l => l.Alias == x.Alias) == false)
|
||||
.ToArray();
|
||||
|
||||
hasChanges = unregistered.Any();
|
||||
|
||||
var count = 0;
|
||||
foreach (var attr in unregistered)
|
||||
{
|
||||
doc.Root.Add(new XElement("add",
|
||||
new XAttribute("alias", attr.Alias),
|
||||
new XAttribute("name", attr.Name),
|
||||
new XAttribute("icon", attr.Icon),
|
||||
new XAttribute("sortOrder", attr.SortOrder)));
|
||||
count++;
|
||||
}
|
||||
|
||||
//don't save if there's no changes
|
||||
return count > 0;
|
||||
}, true);
|
||||
|
||||
if (hasChanges)
|
||||
{
|
||||
//If there were changes, we need to re-read the structures from the XML
|
||||
list = ReadFromXmlAndSort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
internal void LoadXml(Action<XDocument> callback, bool saveAfterCallback)
|
||||
internal void LoadXml(Func<XDocument, bool> callback, bool saveAfterCallbackIfChanged)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
@@ -119,9 +158,9 @@ namespace Umbraco.Core.Services
|
||||
|
||||
if (doc.Root != null)
|
||||
{
|
||||
callback.Invoke(doc);
|
||||
var changed = callback.Invoke(doc);
|
||||
|
||||
if (saveAfterCallback)
|
||||
if (saveAfterCallbackIfChanged && changed)
|
||||
{
|
||||
//ensure the folder is created!
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(AppConfigFilePath));
|
||||
@@ -194,6 +233,7 @@ namespace Umbraco.Core.Services
|
||||
new XAttribute("name", name),
|
||||
new XAttribute("icon", icon),
|
||||
new XAttribute("sortOrder", sortOrder)));
|
||||
return true;
|
||||
}, true);
|
||||
|
||||
//raise event
|
||||
@@ -209,7 +249,7 @@ namespace Umbraco.Core.Services
|
||||
lock (Locker)
|
||||
{
|
||||
//delete the assigned applications
|
||||
ApplicationContext.Current.DatabaseContext.Database.Execute(
|
||||
_uowProvider.GetUnitOfWork().Database.Execute(
|
||||
"delete from umbracoUser2App where app = @appAlias",
|
||||
new { appAlias = section.Alias });
|
||||
|
||||
@@ -222,7 +262,10 @@ namespace Umbraco.Core.Services
|
||||
|
||||
LoadXml(doc =>
|
||||
{
|
||||
doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias).Remove();
|
||||
doc.Root.Elements("add").Where(x => x.Attribute("alias") != null && x.Attribute("alias").Value == section.Alias)
|
||||
.Remove();
|
||||
|
||||
return true;
|
||||
}, true);
|
||||
|
||||
//raise event
|
||||
@@ -230,6 +273,30 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
private List<Section> ReadFromXmlAndSort()
|
||||
{
|
||||
var tmp = new List<Section>();
|
||||
|
||||
LoadXml(doc =>
|
||||
{
|
||||
foreach (var addElement in doc.Root.Elements("add").OrderBy(x =>
|
||||
{
|
||||
var sortOrderAttr = x.Attribute("sortOrder");
|
||||
return sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0;
|
||||
}))
|
||||
{
|
||||
var sortOrderAttr = addElement.Attribute("sortOrder");
|
||||
tmp.Add(new Section(addElement.Attribute("name").Value,
|
||||
addElement.Attribute("alias").Value,
|
||||
addElement.Attribute("icon").Value,
|
||||
sortOrderAttr != null ? Convert.ToInt32(sortOrderAttr.Value) : 0));
|
||||
}
|
||||
return false;
|
||||
}, false);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
internal static event TypedEventHandler<Section, EventArgs> Deleted;
|
||||
private static void OnDeleted(Section app, EventArgs args)
|
||||
{
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Umbraco.Core.Services
|
||||
_treeService = new Lazy<IApplicationTreeService>(() => new ApplicationTreeService(cache));
|
||||
|
||||
if (_sectionService == null)
|
||||
_sectionService = new Lazy<ISectionService>(() => new SectionService(_userService.Value, _treeService.Value, cache));
|
||||
_sectionService = new Lazy<ISectionService>(() => new SectionService(_userService.Value, _treeService.Value, provider, cache));
|
||||
|
||||
if (_macroService == null)
|
||||
_macroService = new Lazy<IMacroService>(() => new MacroService(provider, repositoryFactory.Value));
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Sync
|
||||
@@ -17,23 +18,26 @@ namespace Umbraco.Core.Sync
|
||||
/// status. This will attempt to determine the internal umbraco base url that can be used by the current
|
||||
/// server to send a request to itself if it is in a load balanced environment.
|
||||
/// </summary>
|
||||
/// <returns>The full base url including schema (i.e. http://myserver:80/umbraco )</returns>
|
||||
public static string GetCurrentServerUmbracoBaseUrl()
|
||||
/// <returns>The full base url including schema (i.e. http://myserver:80/umbraco ) - or <c>null</c> if the url
|
||||
/// cannot be determined at the moment (usually because the first request has not properly completed yet).</returns>
|
||||
public static string GetCurrentServerUmbracoBaseUrl(ApplicationContext appContext, IUmbracoSettingsSection settings)
|
||||
{
|
||||
var status = GetStatus();
|
||||
var status = GetStatus(settings);
|
||||
|
||||
if (status == CurrentServerEnvironmentStatus.Single)
|
||||
{
|
||||
//if it's a single install, then the base url has to be the first url registered
|
||||
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
|
||||
// single install, return null if no config/original url, else use config/original url as base
|
||||
// use http or https as appropriate
|
||||
return GetBaseUrl(appContext, settings);
|
||||
}
|
||||
|
||||
var servers = UmbracoConfig.For.UmbracoSettings().DistributedCall.Servers.ToArray();
|
||||
var servers = settings.DistributedCall.Servers.ToArray();
|
||||
|
||||
if (servers.Any() == false)
|
||||
{
|
||||
//cannot be determined, then the base url has to be the first url registered
|
||||
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
|
||||
// cannot be determined, return null if no config/original url, else use config/original url as base
|
||||
// use http or https as appropriate
|
||||
return GetBaseUrl(appContext, settings);
|
||||
}
|
||||
|
||||
foreach (var server in servers)
|
||||
@@ -58,22 +62,23 @@ namespace Umbraco.Core.Sync
|
||||
}
|
||||
}
|
||||
|
||||
//cannot be determined, then the base url has to be the first url registered
|
||||
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
|
||||
// cannot be determined, return null if no config/original url, else use config/original url as base
|
||||
// use http or https as appropriate
|
||||
return GetBaseUrl(appContext, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current environment status for the current server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static CurrentServerEnvironmentStatus GetStatus()
|
||||
public static CurrentServerEnvironmentStatus GetStatus(IUmbracoSettingsSection settings)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled == false)
|
||||
if (settings.DistributedCall.Enabled == false)
|
||||
{
|
||||
return CurrentServerEnvironmentStatus.Single;
|
||||
}
|
||||
|
||||
var servers = UmbracoConfig.For.UmbracoSettings().DistributedCall.Servers.ToArray();
|
||||
var servers = settings.DistributedCall.Servers.ToArray();
|
||||
|
||||
if (servers.Any() == false)
|
||||
{
|
||||
@@ -108,5 +113,21 @@ namespace Umbraco.Core.Sync
|
||||
|
||||
return CurrentServerEnvironmentStatus.Slave;
|
||||
}
|
||||
|
||||
private static string GetBaseUrl(ApplicationContext appContext, IUmbracoSettingsSection settings)
|
||||
{
|
||||
return (
|
||||
// is config empty?
|
||||
settings.ScheduledTasks.BaseUrl.IsNullOrWhiteSpace()
|
||||
// is the orig req empty?
|
||||
? appContext.OriginalRequestUrl.IsNullOrWhiteSpace()
|
||||
// we've got nothing
|
||||
? null
|
||||
//the orig req url is not null, use that
|
||||
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", appContext.OriginalRequestUrl)
|
||||
// the config has been specified, use that
|
||||
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", settings.ScheduledTasks.BaseUrl))
|
||||
.EnsureEndsWith('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ using System.Web.Compilation;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -450,14 +451,23 @@ namespace Umbraco.Core
|
||||
var allTypes = GetTypesWithFormattedException(a)
|
||||
.ToArray();
|
||||
|
||||
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes but have
|
||||
//the specified attribute
|
||||
var attributedTypes = allTypes
|
||||
.Where(t => (TypeHelper.IsNonStaticClass(t)
|
||||
&& (onlyConcreteClasses == false || t.IsAbstract == false))
|
||||
//the type must have this attribute
|
||||
&& t.GetCustomAttributes(attributeType, false).Any())
|
||||
.ToArray();
|
||||
var attributedTypes = new Type[] {};
|
||||
try
|
||||
{
|
||||
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes but have
|
||||
//the specified attribute
|
||||
attributedTypes = allTypes
|
||||
.Where(t => (TypeHelper.IsNonStaticClass(t)
|
||||
&& (onlyConcreteClasses == false || t.IsAbstract == false))
|
||||
//the type must have this attribute
|
||||
&& t.GetCustomAttributes(attributeType, false).Any())
|
||||
.ToArray();
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
//add the types to our list to return
|
||||
foreach (var t in attributedTypes)
|
||||
@@ -583,16 +593,25 @@ namespace Umbraco.Core
|
||||
.Where(assignTypeFrom.IsAssignableFrom)
|
||||
.ToArray();
|
||||
|
||||
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes
|
||||
var filteredTypes = allSubTypes
|
||||
.Where(t => (TypeHelper.IsNonStaticClass(t)
|
||||
//Do not include nested private classes - since we are in full trust now this will find those too!
|
||||
&& t.IsNestedPrivate == false
|
||||
&& (onlyConcreteClasses == false || t.IsAbstract == false)
|
||||
//Do not include classes that are flagged to hide from the type finder
|
||||
&& t.GetCustomAttribute<HideFromTypeFinderAttribute>() == null
|
||||
&& additionalFilter(t)))
|
||||
.ToArray();
|
||||
var filteredTypes = new Type[] { };
|
||||
try
|
||||
{
|
||||
//now filter the types based on the onlyConcreteClasses flag, not interfaces, not static classes
|
||||
filteredTypes = allSubTypes
|
||||
.Where(t => (TypeHelper.IsNonStaticClass(t)
|
||||
//Do not include nested private classes - since we are in full trust now this will find those too!
|
||||
&& t.IsNestedPrivate == false
|
||||
&& (onlyConcreteClasses == false || t.IsAbstract == false)
|
||||
//Do not include classes that are flagged to hide from the type finder
|
||||
&& t.GetCustomAttribute<HideFromTypeFinderAttribute>() == null
|
||||
&& additionalFilter(t)))
|
||||
.ToArray();
|
||||
}
|
||||
catch (TypeLoadException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(TypeFinder), string.Format("Could not query types on {0} assembly, this is most likely due to this assembly not being compatible with the current Umbraco version", a), ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
//add the types to our list to return
|
||||
foreach (var t in filteredTypes)
|
||||
|
||||
@@ -394,6 +394,7 @@
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSixTwoZero\ChangePasswordColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSixTwoZero\UpdateToNewMemberPropertyAliases.cs" />
|
||||
<Compile Include="Persistence\DbConnectionExtensions.cs" />
|
||||
<Compile Include="Persistence\SqlSyntax\MicrosoftSqlSyntaxProviderBase.cs" />
|
||||
<Compile Include="PropertyEditors\DefaultPropertyValueConverterAttribute.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSeven\UpdateRelatedLinksData.cs" />
|
||||
<Compile Include="PropertyEditors\IValueEditor.cs" />
|
||||
|
||||
+118
-119
@@ -1,120 +1,119 @@
|
||||
using System.Configuration;
|
||||
using System.Web.Routing;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class GlobalSettingsTests : BaseWebTest
|
||||
{
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SettingsForTests.UmbracoPath = "~/umbraco";
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
//ensure this is reset
|
||||
SystemDirectories.Root = null;
|
||||
SettingsForTests.UmbracoPath = "~/umbraco";
|
||||
//reset the app config
|
||||
base.TearDown();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Debug_Mode()
|
||||
{
|
||||
Assert.That(Umbraco.Core.Configuration.GlobalSettings.DebugMode, Is.EqualTo(true));
|
||||
}
|
||||
|
||||
[Ignore]
|
||||
[Test]
|
||||
public void Is_Version_From_Assembly_Correct()
|
||||
{
|
||||
Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0"));
|
||||
}
|
||||
|
||||
[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/")]
|
||||
[TestCase("/install")]
|
||||
[TestCase("/install/?installStep=asdf")]
|
||||
[TestCase("/install/test.aspx")]
|
||||
[TestCase("/config/splashes/booting.aspx")]
|
||||
public void Is_Reserved_Path_Or_Url(string url)
|
||||
{
|
||||
Assert.IsTrue(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
|
||||
}
|
||||
|
||||
[TestCase("/umbraco_client/Tree/treeIcons.css")]
|
||||
[TestCase("/umbraco_client/Tree/Themes/umbraco/style.css")]
|
||||
[TestCase("/umbraco_client/scrollingmenu/style.css")]
|
||||
[TestCase("/base/somebasehandler")]
|
||||
[TestCase("/")]
|
||||
[TestCase("/home.aspx")]
|
||||
[TestCase("/umbraco-test")]
|
||||
[TestCase("/install-test")]
|
||||
[TestCase("/install.aspx")]
|
||||
public void Is_Not_Reserved_Path_Or_Url(string url)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Configurations
|
||||
{
|
||||
[TestFixture]
|
||||
public class GlobalSettingsTests : BaseWebTest
|
||||
{
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SettingsForTests.UmbracoPath = "~/umbraco";
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
//ensure this is reset
|
||||
SystemDirectories.Root = null;
|
||||
SettingsForTests.UmbracoPath = "~/umbraco";
|
||||
//reset the app config
|
||||
base.TearDown();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Debug_Mode()
|
||||
{
|
||||
Assert.That(Umbraco.Core.Configuration.GlobalSettings.DebugMode, Is.EqualTo(true));
|
||||
}
|
||||
|
||||
[Ignore]
|
||||
[Test]
|
||||
public void Is_Version_From_Assembly_Correct()
|
||||
{
|
||||
Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0"));
|
||||
}
|
||||
|
||||
[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/")]
|
||||
[TestCase("/install")]
|
||||
[TestCase("/install/?installStep=asdf")]
|
||||
[TestCase("/install/test.aspx")]
|
||||
[TestCase("/config/splashes/booting.aspx")]
|
||||
public void Is_Reserved_Path_Or_Url(string url)
|
||||
{
|
||||
Assert.IsTrue(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url));
|
||||
}
|
||||
|
||||
[TestCase("/umbraco_client/Tree/treeIcons.css")]
|
||||
[TestCase("/umbraco_client/Tree/Themes/umbraco/style.css")]
|
||||
[TestCase("/umbraco_client/scrollingmenu/style.css")]
|
||||
[TestCase("/base/somebasehandler")]
|
||||
[TestCase("/")]
|
||||
[TestCase("/home.aspx")]
|
||||
[TestCase("/umbraco-test")]
|
||||
[TestCase("/install-test")]
|
||||
[TestCase("/install.aspx")]
|
||||
public void Is_Not_Reserved_Path_Or_Url(string url)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
+87
-90
@@ -1,90 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Surface
|
||||
{
|
||||
[TestFixture]
|
||||
public class PluginControllerAreaTests : BaseWebTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Ensure_Same_Area1()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
new PluginControllerArea(new PluginControllerMetadata[]
|
||||
{
|
||||
PluginController.GetMetadata(typeof(Plugin1Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin2Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin3Controller)) //not same area
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Same_Area3()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
new PluginControllerArea(new PluginControllerMetadata[]
|
||||
{
|
||||
PluginController.GetMetadata(typeof(Plugin1Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin2Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin4Controller)) //no area assigned
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Same_Area2()
|
||||
{
|
||||
var area = new PluginControllerArea(new PluginControllerMetadata[]
|
||||
{
|
||||
PluginController.GetMetadata(typeof(Plugin1Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin2Controller))
|
||||
});
|
||||
Assert.Pass();
|
||||
}
|
||||
|
||||
#region Test classes
|
||||
|
||||
[PluginController("Area1")]
|
||||
public class Plugin1Controller : PluginController
|
||||
{
|
||||
public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[PluginController("Area1")]
|
||||
public class Plugin2Controller : PluginController
|
||||
{
|
||||
public Plugin2Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[PluginController("Area2")]
|
||||
public class Plugin3Controller : PluginController
|
||||
{
|
||||
public Plugin3Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Plugin4Controller : PluginController
|
||||
{
|
||||
public Plugin4Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Controllers
|
||||
{
|
||||
[TestFixture]
|
||||
public class PluginControllerAreaTests : BaseWebTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Ensure_Same_Area1()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
new PluginControllerArea(new PluginControllerMetadata[]
|
||||
{
|
||||
PluginController.GetMetadata(typeof(Plugin1Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin2Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin3Controller)) //not same area
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Same_Area3()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
new PluginControllerArea(new PluginControllerMetadata[]
|
||||
{
|
||||
PluginController.GetMetadata(typeof(Plugin1Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin2Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin4Controller)) //no area assigned
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_Same_Area2()
|
||||
{
|
||||
var area = new PluginControllerArea(new PluginControllerMetadata[]
|
||||
{
|
||||
PluginController.GetMetadata(typeof(Plugin1Controller)),
|
||||
PluginController.GetMetadata(typeof(Plugin2Controller))
|
||||
});
|
||||
Assert.Pass();
|
||||
}
|
||||
|
||||
#region Test classes
|
||||
|
||||
[PluginController("Area1")]
|
||||
public class Plugin1Controller : PluginController
|
||||
{
|
||||
public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[PluginController("Area1")]
|
||||
public class Plugin2Controller : PluginController
|
||||
{
|
||||
public Plugin2Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[PluginController("Area2")]
|
||||
public class Plugin3Controller : PluginController
|
||||
{
|
||||
public Plugin3Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Plugin4Controller : PluginController
|
||||
{
|
||||
public Plugin4Controller(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
+209
-210
@@ -1,211 +1,210 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Web.Cache;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Tests.Sync
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures that calls to DistributedCache methods carry through to the IServerMessenger correctly
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class DistributedCacheTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
|
||||
new TestServerRegistrar());
|
||||
ServerMessengerResolver.Current = new ServerMessengerResolver(
|
||||
new TestServerMessenger());
|
||||
CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) });
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
ServerRegistrarResolver.Reset();
|
||||
ServerMessengerResolver.Reset();
|
||||
CacheRefreshersResolver.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshIntId()
|
||||
{
|
||||
for (var i = 1; i < 11; i++)
|
||||
{
|
||||
DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
}
|
||||
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshIntIdFromObject()
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
DistributedCache.Instance.Refresh(
|
||||
Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"),
|
||||
x => x.Id,
|
||||
new TestObjectWithId{Id = i});
|
||||
}
|
||||
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshGuidId()
|
||||
{
|
||||
for (var i = 0; i < 11; i++)
|
||||
{
|
||||
DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
|
||||
}
|
||||
Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveIds()
|
||||
{
|
||||
for (var i = 1; i < 13; i++)
|
||||
{
|
||||
DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
}
|
||||
Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FullRefreshes()
|
||||
{
|
||||
for (var i = 0; i < 13; i++)
|
||||
{
|
||||
DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
|
||||
}
|
||||
Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes);
|
||||
}
|
||||
|
||||
#region internal test classes
|
||||
|
||||
internal class TestObjectWithId
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
internal class TestCacheRefresher : ICacheRefresher
|
||||
{
|
||||
public Guid UniqueIdentifier
|
||||
{
|
||||
get { return Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"); }
|
||||
}
|
||||
public string Name
|
||||
{
|
||||
get { return "Test"; }
|
||||
}
|
||||
public void RefreshAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Refresh(int id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Remove(int id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Refresh(Guid id)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServerMessenger : IServerMessenger
|
||||
{
|
||||
//used for tests
|
||||
public List<int> IntIdsRefreshed = new List<int>();
|
||||
public List<Guid> GuidIdsRefreshed = new List<Guid>();
|
||||
public List<int> IntIdsRemoved = new List<int>();
|
||||
public List<string> PayloadsRemoved = new List<string>();
|
||||
public List<string> PayloadsRefreshed = new List<string>();
|
||||
public int CountOfFullRefreshes = 0;
|
||||
|
||||
|
||||
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
|
||||
{
|
||||
PayloadsRefreshed.Add(jsonPayload);
|
||||
}
|
||||
|
||||
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
|
||||
{
|
||||
IntIdsRefreshed.AddRange(instances.Select(getNumericId));
|
||||
}
|
||||
|
||||
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, Guid> getGuidId, params T[] instances)
|
||||
{
|
||||
GuidIdsRefreshed.AddRange(instances.Select(getGuidId));
|
||||
}
|
||||
|
||||
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
|
||||
{
|
||||
PayloadsRemoved.Add(jsonPayload);
|
||||
}
|
||||
|
||||
public void PerformRemove<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
|
||||
{
|
||||
IntIdsRemoved.AddRange(instances.Select(getNumericId));
|
||||
}
|
||||
|
||||
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
|
||||
{
|
||||
IntIdsRemoved.AddRange(numericIds);
|
||||
}
|
||||
|
||||
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
|
||||
{
|
||||
IntIdsRefreshed.AddRange(numericIds);
|
||||
}
|
||||
|
||||
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params Guid[] guidIds)
|
||||
{
|
||||
GuidIdsRefreshed.AddRange(guidIds);
|
||||
}
|
||||
|
||||
public void PerformRefreshAll(IEnumerable<IServerAddress> servers, ICacheRefresher refresher)
|
||||
{
|
||||
CountOfFullRefreshes++;
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServerRegistrar : IServerRegistrar
|
||||
{
|
||||
public IEnumerable<IServerAddress> Registrations
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<IServerAddress>()
|
||||
{
|
||||
new TestServerAddress("localhost")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestServerAddress : IServerAddress
|
||||
{
|
||||
public TestServerAddress(string address)
|
||||
{
|
||||
ServerAddress = address;
|
||||
}
|
||||
public string ServerAddress { get; private set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Sync;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Tests.DistributedCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures that calls to DistributedCache methods carry through to the IServerMessenger correctly
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class DistributedCacheTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
|
||||
new TestServerRegistrar());
|
||||
ServerMessengerResolver.Current = new ServerMessengerResolver(
|
||||
new TestServerMessenger());
|
||||
CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) });
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
ServerRegistrarResolver.Reset();
|
||||
ServerMessengerResolver.Reset();
|
||||
CacheRefreshersResolver.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshIntId()
|
||||
{
|
||||
for (var i = 1; i < 11; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
}
|
||||
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshIntIdFromObject()
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Refresh(
|
||||
Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"),
|
||||
x => x.Id,
|
||||
new TestObjectWithId{Id = i});
|
||||
}
|
||||
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshGuidId()
|
||||
{
|
||||
for (var i = 0; i < 11; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
|
||||
}
|
||||
Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveIds()
|
||||
{
|
||||
for (var i = 1; i < 13; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
}
|
||||
Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FullRefreshes()
|
||||
{
|
||||
for (var i = 0; i < 13; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
|
||||
}
|
||||
Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes);
|
||||
}
|
||||
|
||||
#region internal test classes
|
||||
|
||||
internal class TestObjectWithId
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
internal class TestCacheRefresher : ICacheRefresher
|
||||
{
|
||||
public Guid UniqueIdentifier
|
||||
{
|
||||
get { return Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"); }
|
||||
}
|
||||
public string Name
|
||||
{
|
||||
get { return "Test"; }
|
||||
}
|
||||
public void RefreshAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Refresh(int id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Remove(int id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Refresh(Guid id)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServerMessenger : IServerMessenger
|
||||
{
|
||||
//used for tests
|
||||
public List<int> IntIdsRefreshed = new List<int>();
|
||||
public List<Guid> GuidIdsRefreshed = new List<Guid>();
|
||||
public List<int> IntIdsRemoved = new List<int>();
|
||||
public List<string> PayloadsRemoved = new List<string>();
|
||||
public List<string> PayloadsRefreshed = new List<string>();
|
||||
public int CountOfFullRefreshes = 0;
|
||||
|
||||
|
||||
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
|
||||
{
|
||||
PayloadsRefreshed.Add(jsonPayload);
|
||||
}
|
||||
|
||||
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
|
||||
{
|
||||
IntIdsRefreshed.AddRange(instances.Select(getNumericId));
|
||||
}
|
||||
|
||||
public void PerformRefresh<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, Guid> getGuidId, params T[] instances)
|
||||
{
|
||||
GuidIdsRefreshed.AddRange(instances.Select(getGuidId));
|
||||
}
|
||||
|
||||
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, string jsonPayload)
|
||||
{
|
||||
PayloadsRemoved.Add(jsonPayload);
|
||||
}
|
||||
|
||||
public void PerformRemove<T>(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, Func<T, int> getNumericId, params T[] instances)
|
||||
{
|
||||
IntIdsRemoved.AddRange(instances.Select(getNumericId));
|
||||
}
|
||||
|
||||
public void PerformRemove(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
|
||||
{
|
||||
IntIdsRemoved.AddRange(numericIds);
|
||||
}
|
||||
|
||||
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params int[] numericIds)
|
||||
{
|
||||
IntIdsRefreshed.AddRange(numericIds);
|
||||
}
|
||||
|
||||
public void PerformRefresh(IEnumerable<IServerAddress> servers, ICacheRefresher refresher, params Guid[] guidIds)
|
||||
{
|
||||
GuidIdsRefreshed.AddRange(guidIds);
|
||||
}
|
||||
|
||||
public void PerformRefreshAll(IEnumerable<IServerAddress> servers, ICacheRefresher refresher)
|
||||
{
|
||||
CountOfFullRefreshes++;
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServerRegistrar : IServerRegistrar
|
||||
{
|
||||
public IEnumerable<IServerAddress> Registrations
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<IServerAddress>()
|
||||
{
|
||||
new TestServerAddress("localhost")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestServerAddress : IServerAddress
|
||||
{
|
||||
public TestServerAddress(string address)
|
||||
{
|
||||
ServerAddress = address;
|
||||
}
|
||||
public string ServerAddress { get; private set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+158
-162
@@ -1,162 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Web.Dynamics;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Tests.Dynamics
|
||||
{
|
||||
//NOTE: there's libraries in both Umbraco.Core.Dynamics and Umbraco.Web.Dynamics - the reason for this is that the Web.Dynamics
|
||||
// started with the razor macro implementation and is modified with hard coded references to dynamic node and dynamic null, though it seems
|
||||
// to still work for other regular classes I don't want to move it to the core without removing these references but that would require a lot of work.
|
||||
|
||||
[TestFixture]
|
||||
public class QueryableExtensionTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Order_By_Test_Int()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().OrderBy("Age").ToArray();
|
||||
|
||||
Assert.AreEqual(10, result.ElementAt(0).Age);
|
||||
Assert.AreEqual(11, result.ElementAt(1).Age);
|
||||
Assert.AreEqual(12, result.ElementAt(2).Age);
|
||||
Assert.AreEqual(20, result.ElementAt(3).Age);
|
||||
Assert.AreEqual(31, result.ElementAt(4).Age);
|
||||
Assert.AreEqual(55, result.ElementAt(5).Age);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Order_By_Test_String()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().OrderBy("Name").ToArray();
|
||||
|
||||
Assert.AreEqual("anothertest", result.ElementAt(0).Name);
|
||||
Assert.AreEqual("blah", result.ElementAt(1).Name);
|
||||
Assert.AreEqual("someguy", result.ElementAt(2).Name);
|
||||
Assert.AreEqual("test1", result.ElementAt(3).Name);
|
||||
Assert.AreEqual("test2", result.ElementAt(4).Name);
|
||||
Assert.AreEqual("test3", result.ElementAt(5).Name);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_String()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().Where("Name = \"test1\"").ToArray();
|
||||
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual("test1", result.ElementAt(0).Name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_String_With_Params()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
//NOTE: Currently the object query structure is not supported
|
||||
//var result = items.AsQueryable().Where("Name = @name", new {name = "test1"}).ToArray();
|
||||
var result = items.AsQueryable().Where("Name = @Name", new Dictionary<string, object> { { "Name", "test1" } }).ToArray();
|
||||
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual("test1", result.ElementAt(0).Name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_Int_With_Params()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().Where("Age = @Age", new Dictionary<string, object> { { "Age", 10 } }).ToArray();
|
||||
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual("test1", result.ElementAt(0).Name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_Bool_With_Params()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().Where("Female = @Female", new Dictionary<string, object> { { "Female", true } }).ToArray();
|
||||
|
||||
Assert.AreEqual(2, result.Count());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class TestModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
public bool Female { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Web.Dynamics;
|
||||
|
||||
namespace Umbraco.Tests.DynamicsAndReflection
|
||||
{
|
||||
//NOTE: there's libraries in both Umbraco.Core.Dynamics and Umbraco.Web.Dynamics - the reason for this is that the Web.Dynamics
|
||||
// started with the razor macro implementation and is modified with hard coded references to dynamic node and dynamic null, though it seems
|
||||
// to still work for other regular classes I don't want to move it to the core without removing these references but that would require a lot of work.
|
||||
|
||||
[TestFixture]
|
||||
public class QueryableExtensionTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Order_By_Test_Int()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().OrderBy("Age").ToArray();
|
||||
|
||||
Assert.AreEqual(10, result.ElementAt(0).Age);
|
||||
Assert.AreEqual(11, result.ElementAt(1).Age);
|
||||
Assert.AreEqual(12, result.ElementAt(2).Age);
|
||||
Assert.AreEqual(20, result.ElementAt(3).Age);
|
||||
Assert.AreEqual(31, result.ElementAt(4).Age);
|
||||
Assert.AreEqual(55, result.ElementAt(5).Age);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Order_By_Test_String()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().OrderBy("Name").ToArray();
|
||||
|
||||
Assert.AreEqual("anothertest", result.ElementAt(0).Name);
|
||||
Assert.AreEqual("blah", result.ElementAt(1).Name);
|
||||
Assert.AreEqual("someguy", result.ElementAt(2).Name);
|
||||
Assert.AreEqual("test1", result.ElementAt(3).Name);
|
||||
Assert.AreEqual("test2", result.ElementAt(4).Name);
|
||||
Assert.AreEqual("test3", result.ElementAt(5).Name);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_String()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().Where("Name = \"test1\"").ToArray();
|
||||
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual("test1", result.ElementAt(0).Name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_String_With_Params()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
//NOTE: Currently the object query structure is not supported
|
||||
//var result = items.AsQueryable().Where("Name = @name", new {name = "test1"}).ToArray();
|
||||
var result = items.AsQueryable().Where("Name = @Name", new Dictionary<string, object> { { "Name", "test1" } }).ToArray();
|
||||
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual("test1", result.ElementAt(0).Name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_Int_With_Params()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().Where("Age = @Age", new Dictionary<string, object> { { "Age", 10 } }).ToArray();
|
||||
|
||||
Assert.AreEqual(1, result.Count());
|
||||
Assert.AreEqual("test1", result.ElementAt(0).Name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Test_Bool_With_Params()
|
||||
{
|
||||
var items = new List<TestModel>
|
||||
{
|
||||
new TestModel {Age = 10, Name = "test1", Female = false},
|
||||
new TestModel {Age = 31, Name = "someguy", Female = true},
|
||||
new TestModel {Age = 11, Name = "test2", Female = true},
|
||||
new TestModel {Age = 20, Name = "anothertest", Female = false},
|
||||
new TestModel {Age = 55, Name = "blah", Female = false},
|
||||
new TestModel {Age = 12, Name = "test3", Female = false}
|
||||
};
|
||||
|
||||
var result = items.AsQueryable().Where("Female = @Female", new Dictionary<string, object> { { "Female", true } }).ToArray();
|
||||
|
||||
Assert.AreEqual(2, result.Count());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class TestModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
public bool Female { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+138
-138
@@ -1,139 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using umbraco.cms.businesslogic.macro;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class MacroEngineFactoryTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
{
|
||||
this.GetType().Assembly
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
PluginManager.Current = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_All()
|
||||
{
|
||||
var engines = MacroEngineFactory.GetAll();
|
||||
Assert.AreEqual(2, engines.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Engine()
|
||||
{
|
||||
var engine1 = MacroEngineFactory.GetEngine("MacroEngine1");
|
||||
Assert.IsNotNull(engine1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_By_Filename()
|
||||
{
|
||||
var engine1 = MacroEngineFactory.GetByFilename("test.me1");
|
||||
var engine2 = MacroEngineFactory.GetByFilename("test.me2");
|
||||
Assert.IsNotNull(engine1);
|
||||
Assert.IsNotNull(engine2);
|
||||
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByFilename("test.blah"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_By_Extension()
|
||||
{
|
||||
var engine1 = MacroEngineFactory.GetByExtension("me1");
|
||||
var engine2 = MacroEngineFactory.GetByExtension("me2");
|
||||
Assert.IsNotNull(engine1);
|
||||
Assert.IsNotNull(engine2);
|
||||
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByExtension("blah"));
|
||||
}
|
||||
|
||||
#region Classes for tests
|
||||
public class MacroEngine1 : IMacroEngine
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return "MacroEngine1"; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedExtensions
|
||||
{
|
||||
get { return new[] {"me1"}; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedUIExtensions
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public Dictionary<string, IMacroGuiRendering> SupportedProperties
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string Execute(MacroModel macro, INode currentPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class MacroEngine2 : IMacroEngine
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return "MacroEngine2"; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedExtensions
|
||||
{
|
||||
get { return new[] { "me2" }; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedUIExtensions
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public Dictionary<string, IMacroGuiRendering> SupportedProperties
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string Execute(MacroModel macro, INode currentPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.businesslogic.macro;
|
||||
using Umbraco.Core;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Macros
|
||||
{
|
||||
[TestFixture]
|
||||
public class MacroEngineFactoryTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//this ensures its reset
|
||||
PluginManager.Current = new PluginManager(false);
|
||||
|
||||
//for testing, we'll specify which assemblies are scanned for the PluginTypeResolver
|
||||
PluginManager.Current.AssembliesToScan = new[]
|
||||
{
|
||||
this.GetType().Assembly
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
PluginManager.Current = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_All()
|
||||
{
|
||||
var engines = MacroEngineFactory.GetAll();
|
||||
Assert.AreEqual(2, engines.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Engine()
|
||||
{
|
||||
var engine1 = MacroEngineFactory.GetEngine("MacroEngine1");
|
||||
Assert.IsNotNull(engine1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_By_Filename()
|
||||
{
|
||||
var engine1 = MacroEngineFactory.GetByFilename("test.me1");
|
||||
var engine2 = MacroEngineFactory.GetByFilename("test.me2");
|
||||
Assert.IsNotNull(engine1);
|
||||
Assert.IsNotNull(engine2);
|
||||
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByFilename("test.blah"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_By_Extension()
|
||||
{
|
||||
var engine1 = MacroEngineFactory.GetByExtension("me1");
|
||||
var engine2 = MacroEngineFactory.GetByExtension("me2");
|
||||
Assert.IsNotNull(engine1);
|
||||
Assert.IsNotNull(engine2);
|
||||
Assert.Throws<MacroEngineException>(() => MacroEngineFactory.GetByExtension("blah"));
|
||||
}
|
||||
|
||||
#region Classes for tests
|
||||
public class MacroEngine1 : IMacroEngine
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return "MacroEngine1"; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedExtensions
|
||||
{
|
||||
get { return new[] {"me1"}; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedUIExtensions
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public Dictionary<string, IMacroGuiRendering> SupportedProperties
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string Execute(MacroModel macro, INode currentPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class MacroEngine2 : IMacroEngine
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get { return "MacroEngine2"; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedExtensions
|
||||
{
|
||||
get { return new[] { "me2" }; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedUIExtensions
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public Dictionary<string, IMacroGuiRendering> SupportedProperties
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string Execute(MacroModel macro, INode currentPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+32
-32
@@ -1,33 +1,33 @@
|
||||
using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class HtmlHelperExtensionMethodsTests
|
||||
{
|
||||
[SetUp]
|
||||
public virtual void Initialize()
|
||||
{
|
||||
//create an empty htmlHelper
|
||||
_htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage());
|
||||
}
|
||||
|
||||
private HtmlHelper _htmlHelper;
|
||||
|
||||
[Test]
|
||||
public void Wrap_Simple()
|
||||
{
|
||||
var output = _htmlHelper.Wrap("div", "hello world");
|
||||
Assert.AreEqual("<div>hello world</div>", output.ToHtmlString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Wrap_Object_Attributes()
|
||||
{
|
||||
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
|
||||
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
|
||||
}
|
||||
}
|
||||
using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class HtmlHelperExtensionMethodsTests
|
||||
{
|
||||
[SetUp]
|
||||
public virtual void Initialize()
|
||||
{
|
||||
//create an empty htmlHelper
|
||||
_htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage());
|
||||
}
|
||||
|
||||
private HtmlHelper _htmlHelper;
|
||||
|
||||
[Test]
|
||||
public void Wrap_Simple()
|
||||
{
|
||||
var output = _htmlHelper.Wrap("div", "hello world");
|
||||
Assert.AreEqual("<div>hello world</div>", output.ToHtmlString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Wrap_Object_Attributes()
|
||||
{
|
||||
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
|
||||
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,7 +408,7 @@ namespace Umbraco.Tests.Mvc
|
||||
var ctx = new UmbracoContext(
|
||||
GetHttpContextFactory(url, routeData).HttpContext,
|
||||
appCtx,
|
||||
new PublishedCaches(cache, new PublishedMediaCache()),
|
||||
new PublishedCaches(cache, new PublishedMediaCache(appCtx)),
|
||||
new WebSecurity(http, appCtx));
|
||||
|
||||
//if (setSingleton)
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
//using System;
|
||||
//using System.Linq;
|
||||
//using NUnit.Framework;
|
||||
//using Umbraco.Core.Models;
|
||||
//using Umbraco.Core.Persistence;
|
||||
//using Umbraco.Core.Persistence.SqlSyntax;
|
||||
//using Umbraco.Tests.TestHelpers;
|
||||
//using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
//namespace Umbraco.Tests.Persistence
|
||||
//{
|
||||
// [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
|
||||
// [TestFixture]
|
||||
// public class PetaPocoDynamicQueryTests : BaseDatabaseFactoryTest
|
||||
// {
|
||||
// [Test]
|
||||
// public void Check_Poco_Storage_Growth()
|
||||
// {
|
||||
// //CreateStuff();
|
||||
|
||||
// for (int i = 0; i < 1000; i++)
|
||||
// {
|
||||
// DatabaseContext.Database.Fetch<dynamic>(
|
||||
// "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='" + i + "'");
|
||||
// }
|
||||
|
||||
// //var oc11 = Database.PocoData.GetCachedPocoData().Count();
|
||||
// //var oc12 = Database.PocoData.GetConverters().Count();
|
||||
// //var oc13 = Database.GetAutoMappers().Count();
|
||||
// //var oc14 = Database.GetMultiPocoFactories().Count();
|
||||
|
||||
// //for (int i = 0; i < 2; i++)
|
||||
// //{
|
||||
// // i1 = DatabaseContext.Database.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
|
||||
// // r1 = i1.Select(x => x.TABLE_NAME).Cast<string>().ToList();
|
||||
// //}
|
||||
|
||||
// //var oc21 = Database.PocoData.GetCachedPocoData().Count();
|
||||
// //var oc22 = Database.PocoData.GetConverters().Count();
|
||||
// //var oc23 = Database.GetAutoMappers().Count();
|
||||
// //var oc24 = Database.GetMultiPocoFactories().Count();
|
||||
|
||||
// //var roots = ServiceContext.ContentService.GetRootContent();
|
||||
// //foreach (var content in roots)
|
||||
// //{
|
||||
// // var d = ServiceContext.ContentService.GetDescendants(content);
|
||||
// //}
|
||||
|
||||
// //var oc31 = Database.PocoData.GetCachedPocoData().Count();
|
||||
// //var oc32 = Database.PocoData.GetConverters().Count();
|
||||
// //var oc33 = Database.GetAutoMappers().Count();
|
||||
// //var oc34 = Database.GetMultiPocoFactories().Count();
|
||||
|
||||
// //for (int i = 0; i < 2; i++)
|
||||
// //{
|
||||
// // roots = ServiceContext.ContentService.GetRootContent();
|
||||
// // foreach (var content in roots)
|
||||
// // {
|
||||
// // var d = ServiceContext.ContentService.GetDescendants(content);
|
||||
// // }
|
||||
// //}
|
||||
|
||||
// //var oc41 = Database.PocoData.GetCachedPocoData().Count();
|
||||
// //var oc42 = Database.PocoData.GetConverters().Count();
|
||||
// //var oc43 = Database.GetAutoMappers().Count();
|
||||
// //var oc44 = Database.GetMultiPocoFactories().Count();
|
||||
|
||||
// //var i2 = DatabaseContext.Database.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS");
|
||||
// //var r2 =
|
||||
// // i2.Select(
|
||||
// // item =>
|
||||
// // new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
|
||||
// // item.IS_NULLABLE, item.DATA_TYPE)).ToList();
|
||||
|
||||
|
||||
// var pocoData = Database.PocoData.GetCachedPocoData();
|
||||
// Console.WriteLine("GetCachedPocoData: " + pocoData.Count());
|
||||
// foreach (var keyValuePair in pocoData)
|
||||
// {
|
||||
// Console.WriteLine(keyValuePair.Value.GetFactories().Count());
|
||||
// }
|
||||
|
||||
// Console.WriteLine("GetConverters: " + Database.PocoData.GetConverters().Count());
|
||||
// Console.WriteLine("GetAutoMappers: " + Database.GetAutoMappers().Count());
|
||||
// Console.WriteLine("GetMultiPocoFactories: " + Database.GetMultiPocoFactories().Count());
|
||||
|
||||
// //Assert.AreEqual(oc11, oc21);
|
||||
// //Assert.AreEqual(oc12, oc22);
|
||||
// //Assert.AreEqual(oc13, oc23);
|
||||
// //Assert.AreEqual(oc14, oc24);
|
||||
|
||||
// //Assert.AreEqual(oc31, oc41);
|
||||
// //Assert.AreEqual(oc32, oc42);
|
||||
// //Assert.AreEqual(oc33, oc43);
|
||||
// //Assert.AreEqual(oc34, oc44);
|
||||
// }
|
||||
|
||||
// public void CreateStuff()
|
||||
// {
|
||||
// var contentType1 = MockedContentTypes.CreateTextpageContentType("test1", "test1");
|
||||
// var contentType2 = MockedContentTypes.CreateTextpageContentType("test2", "test2");
|
||||
// var contentType3 = MockedContentTypes.CreateTextpageContentType("test3", "test3");
|
||||
// ServiceContext.ContentTypeService.Save(new[] { contentType1, contentType2, contentType3 });
|
||||
// contentType1.AllowedContentTypes = new[]
|
||||
// {
|
||||
// new ContentTypeSort(new Lazy<int>(() => contentType2.Id), 0, contentType2.Alias),
|
||||
// new ContentTypeSort(new Lazy<int>(() => contentType3.Id), 1, contentType3.Alias)
|
||||
// };
|
||||
// contentType2.AllowedContentTypes = new[]
|
||||
// {
|
||||
// new ContentTypeSort(new Lazy<int>(() => contentType1.Id), 0, contentType1.Alias),
|
||||
// new ContentTypeSort(new Lazy<int>(() => contentType3.Id), 1, contentType3.Alias)
|
||||
// };
|
||||
// contentType3.AllowedContentTypes = new[]
|
||||
// {
|
||||
// new ContentTypeSort(new Lazy<int>(() => contentType1.Id), 0, contentType1.Alias),
|
||||
// new ContentTypeSort(new Lazy<int>(() => contentType2.Id), 1, contentType2.Alias)
|
||||
// };
|
||||
// ServiceContext.ContentTypeService.Save(new[] { contentType1, contentType2, contentType3 });
|
||||
|
||||
// var roots = MockedContent.CreateTextpageContent(contentType1, -1, 3);
|
||||
// ServiceContext.ContentService.Save(roots);
|
||||
// foreach (var root in roots)
|
||||
// {
|
||||
// var item1 = MockedContent.CreateTextpageContent(contentType1, root.Id, 3);
|
||||
// var item2 = MockedContent.CreateTextpageContent(contentType2, root.Id, 3);
|
||||
// var item3 = MockedContent.CreateTextpageContent(contentType3, root.Id, 3);
|
||||
|
||||
// ServiceContext.ContentService.Save(item1.Concat(item2).Concat(item3));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,14 +1,201 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Persistence
|
||||
{
|
||||
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
|
||||
[TestFixture, NUnit.Framework.Ignore]
|
||||
public class PetaPocoCachesTest : BaseServiceTest
|
||||
{
|
||||
/// <summary>
|
||||
/// This tests the peta poco caches
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This test WILL fail. This is because we cannot stop PetaPoco from creating more cached items for queries such as
|
||||
/// ContentTypeRepository.GetAll(1,2,3,4);
|
||||
/// when combined with other GetAll queries that pass in an array of Ids, each query generated for different length
|
||||
/// arrays will produce a unique query which then gets added to the cache.
|
||||
///
|
||||
/// This test confirms this, if you analyze the DIFFERENCE output below you can see why the cached queries grow.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void Check_Peta_Poco_Caches()
|
||||
{
|
||||
var result = new List<Tuple<double, int, IEnumerable<string>>>();
|
||||
|
||||
Database.PocoData.UseLongKeys = true;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int id1, id2, id3;
|
||||
string alias;
|
||||
CreateStuff(out id1, out id2, out id3, out alias);
|
||||
QueryStuff(id1, id2, id3, alias);
|
||||
|
||||
double totalBytes1;
|
||||
IEnumerable<string> keys;
|
||||
Console.Write(Database.PocoData.PrintDebugCacheReport(out totalBytes1, out keys));
|
||||
|
||||
result.Add(new Tuple<double, int, IEnumerable<string>>(totalBytes1, keys.Count(), keys));
|
||||
}
|
||||
|
||||
for (int index = 0; index < result.Count; index++)
|
||||
{
|
||||
var tuple = result[index];
|
||||
Console.WriteLine("Bytes: {0}, Delegates: {1}", tuple.Item1, tuple.Item2);
|
||||
if (index != 0)
|
||||
{
|
||||
Console.WriteLine("----------------DIFFERENCE---------------------");
|
||||
var diff = tuple.Item3.Except(result[index - 1].Item3);
|
||||
foreach (var d in diff)
|
||||
{
|
||||
Console.WriteLine(d);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var allByteResults = result.Select(x => x.Item1).Distinct();
|
||||
var totalKeys = result.Select(x => x.Item2).Distinct();
|
||||
|
||||
Assert.AreEqual(1, allByteResults.Count());
|
||||
Assert.AreEqual(1, totalKeys.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Verify_Memory_Expires()
|
||||
{
|
||||
Database.PocoData.SlidingExpirationSeconds = 2;
|
||||
|
||||
var managedCache = new Database.ManagedCache();
|
||||
|
||||
int id1, id2, id3;
|
||||
string alias;
|
||||
CreateStuff(out id1, out id2, out id3, out alias);
|
||||
QueryStuff(id1, id2, id3, alias);
|
||||
|
||||
var count1 = managedCache.GetCache().GetCount();
|
||||
Console.WriteLine("Keys = " + count1);
|
||||
Assert.Greater(count1, 0);
|
||||
|
||||
Thread.Sleep(10000);
|
||||
|
||||
var count2 = managedCache.GetCache().GetCount();
|
||||
Console.WriteLine("Keys = " + count2);
|
||||
Assert.Less(count2, count1);
|
||||
}
|
||||
|
||||
private void QueryStuff(int id1, int id2, int id3, string alias1)
|
||||
{
|
||||
var contentService = ServiceContext.ContentService;
|
||||
|
||||
ServiceContext.TagService.GetTagsForEntity(id1);
|
||||
|
||||
ServiceContext.TagService.GetAllContentTags();
|
||||
|
||||
ServiceContext.TagService.GetTagsForEntity(id2);
|
||||
|
||||
ServiceContext.TagService.GetTagsForEntity(id3);
|
||||
|
||||
contentService.CountDescendants(id3);
|
||||
|
||||
contentService.CountChildren(id3);
|
||||
|
||||
contentService.Count(contentTypeAlias: alias1);
|
||||
|
||||
contentService.Count();
|
||||
|
||||
contentService.GetById(Guid.NewGuid());
|
||||
|
||||
contentService.GetByLevel(2);
|
||||
|
||||
contentService.GetChildren(id1);
|
||||
|
||||
contentService.GetDescendants(id2);
|
||||
|
||||
contentService.GetVersions(id3);
|
||||
|
||||
contentService.GetRootContent();
|
||||
|
||||
contentService.GetContentForExpiration();
|
||||
|
||||
contentService.GetContentForRelease();
|
||||
|
||||
contentService.GetContentInRecycleBin();
|
||||
|
||||
((ContentService)contentService).GetPublishedDescendants(new Content("Test", -1, new ContentType(-1))
|
||||
{
|
||||
Id = id1,
|
||||
Path = "-1," + id1
|
||||
});
|
||||
|
||||
contentService.GetByVersion(Guid.NewGuid());
|
||||
}
|
||||
|
||||
private void CreateStuff(out int id1, out int id2, out int id3, out string alias)
|
||||
{
|
||||
var contentService = ServiceContext.ContentService;
|
||||
|
||||
var ctAlias = "umbTextpage" + Guid.NewGuid().ToString("N");
|
||||
alias = ctAlias;
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0);
|
||||
}
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType(ctAlias, "test Doc Type");
|
||||
contentTypeService.Save(contentType);
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0);
|
||||
}
|
||||
var parent = contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0);
|
||||
id1 = parent.Id;
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
contentService.CreateContentWithIdentity("Test", parent, ctAlias);
|
||||
}
|
||||
IContent current = parent;
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
current = contentService.CreateContentWithIdentity("Test", current, ctAlias);
|
||||
}
|
||||
contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory" + Guid.NewGuid().ToString("N"), "Mandatory Doc Type", true);
|
||||
contentType.PropertyGroups.First().PropertyTypes.Add(
|
||||
new PropertyType("test", DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = "tags",
|
||||
DataTypeDefinitionId = 1041
|
||||
});
|
||||
contentTypeService.Save(contentType);
|
||||
var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1);
|
||||
content1.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true);
|
||||
contentService.Publish(content1);
|
||||
id2 = content1.Id;
|
||||
|
||||
var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1);
|
||||
content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true);
|
||||
contentService.Publish(content2);
|
||||
id3 = content2.Id;
|
||||
|
||||
contentService.MoveToRecycleBin(content1);
|
||||
}
|
||||
}
|
||||
|
||||
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
|
||||
[TestFixture]
|
||||
public class PetaPocoExtensionsTest : BaseDatabaseFactoryTest
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = 'c66ba18e-eaf3-4cff-8a22-41b16d66a972'");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -36,6 +36,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
|
||||
@@ -50,8 +56,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = 'c66ba18e-eaf3-4cff-8a22-41b16d66a972'")
|
||||
.Where("[umbracoNode].[id] = 1050");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
|
||||
.Where("[umbracoNode].[id] = @0", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -67,6 +73,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
|
||||
@@ -82,9 +94,9 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin("[cmsContentVersion]").On("[cmsDocument].[versionId] = [cmsContentVersion].[VersionId]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = 'c66ba18e-eaf3-4cff-8a22-41b16d66a972'")
|
||||
.Where("[umbracoNode].[id] = 1050")
|
||||
.Where("[cmsContentVersion].[VersionId] = '2b543516-a944-4ee6-88c6-8813da7aaa07'")
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("c66ba18e-eaf3-4cff-8a22-41b16d66a972"))
|
||||
.Where("[umbracoNode].[id] = @0", 1050)
|
||||
.Where("[cmsContentVersion].[VersionId] = @0", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"))
|
||||
.OrderBy("[cmsContentVersion].[VersionDate] DESC");
|
||||
|
||||
var sql = new Sql();
|
||||
@@ -102,6 +114,11 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
@@ -116,8 +133,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
expected.Select("*");
|
||||
expected.From("[cmsPropertyData]");
|
||||
expected.InnerJoin("[cmsPropertyType]").On("[cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id]");
|
||||
expected.Where("[cmsPropertyData].[contentNodeId] = 1050");
|
||||
expected.Where("[cmsPropertyData].[versionId] = '2b543516-a944-4ee6-88c6-8813da7aaa07'");
|
||||
expected.Where("[cmsPropertyData].[contentNodeId] = @0", 1050);
|
||||
expected.Where("[cmsPropertyData].[versionId] = @0", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -128,6 +145,11 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.Where<PropertyDataDto>(x => x.VersionId == versionId);
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]")
|
||||
.InnerJoin("[umbracoNode]")
|
||||
.On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = 'a2cb7800-f571-4787-9638-bc48539a0efb'")
|
||||
.Where("[cmsDocumentType].[IsDefault] = 1");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
|
||||
.Where("[cmsDocumentType].[IsDefault] = @0", true);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -37,6 +37,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
|
||||
@@ -52,9 +58,9 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.On("[cmsContentType].[nodeId] = [cmsDocumentType].[contentTypeNodeId]")
|
||||
.InnerJoin("[umbracoNode]")
|
||||
.On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = 'a2cb7800-f571-4787-9638-bc48539a0efb'")
|
||||
.Where("[cmsDocumentType].[IsDefault] = 1")
|
||||
.Where("[umbracoNode].[id] = 1050");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"))
|
||||
.Where("[cmsDocumentType].[IsDefault] = @0", true)
|
||||
.Where("[umbracoNode].[id] = @0", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -64,11 +70,17 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentTypeDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectType)
|
||||
.Where<DocumentTypeDto>(x => x.IsDefault == true)
|
||||
.Where<DocumentTypeDto>(x => x.IsDefault)
|
||||
.Where<NodeDto>(x => x.NodeId == 1050);
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
|
||||
@@ -100,7 +112,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var expected = new Sql();
|
||||
expected.Select("*")
|
||||
.From("[cmsContentTypeAllowedContentType]")
|
||||
.Where("[cmsContentTypeAllowedContentType].[Id] = 1050");
|
||||
.Where("[cmsContentTypeAllowedContentType].[Id] = @0", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -109,6 +121,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
|
||||
@@ -120,7 +138,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.From("[cmsPropertyTypeGroup]")
|
||||
.RightJoin("[cmsPropertyType]").On("[cmsPropertyTypeGroup].[id] = [cmsPropertyType].[propertyTypeGroupId]")
|
||||
.InnerJoin("[cmsDataType]").On("[cmsPropertyType].[dataTypeId] = [cmsDataType].[nodeId]")
|
||||
.Where("[cmsPropertyType].[contentTypeId] = 1050");
|
||||
.Where("[cmsPropertyType].[contentTypeId] = @0", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -133,6 +151,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
expected.Select("*")
|
||||
.From("[cmsDataType]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsDataType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = '30a2a501-1978-4ddb-a57b-f7efed43ba3c'");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -30,6 +30,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("upper([umbracoNode].[path]) like '-1%'", result);
|
||||
Assert.AreEqual("upper([umbracoNode].[path]) LIKE upper(@0)", result);
|
||||
Assert.AreEqual("-1%", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -36,7 +37,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("[umbracoNode].[parentID] = -1", result);
|
||||
Assert.AreEqual("[umbracoNode].[parentID] = @0", result);
|
||||
Assert.AreEqual(-1, modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -48,7 +50,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("[umbracoUser].[userLogin] = 'hello@@world.com'", result);
|
||||
Assert.AreEqual("[umbracoUser].[userLogin] = @0", result);
|
||||
Assert.AreEqual("hello@world.com", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -60,7 +63,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("upper([umbracoUser].[userLogin]) = 'HELLO@@WORLD.COM'", result);
|
||||
Assert.AreEqual("upper([umbracoUser].[userLogin]) = upper(@0)", result);
|
||||
Assert.AreEqual("hello@world.com", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -75,7 +79,9 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("upper(`umbracoUser`.`userLogin`) = 'MYDOMAIN\\\\MYUSER'", result);
|
||||
Assert.AreEqual("upper(`umbracoUser`.`userLogin`) = upper(@0)", result);
|
||||
Assert.AreEqual("mydomain\\myuser", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -90,7 +96,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Console.WriteLine("Poco to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("upper(`umbracoUser`.`userLogin`) like 'MYDOMAIN\\\\MYUSER%'", result);
|
||||
Assert.AreEqual("upper(`umbracoUser`.`userLogin`) LIKE upper(@0)", result);
|
||||
Assert.AreEqual("mydomain\\myuser%", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
.From("[cmsContentVersion]")
|
||||
.InnerJoin("[cmsContent]").On("[cmsContentVersion].[ContentId] = [cmsContent].[nodeId]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContent].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = 'b796f64c-1f99-4ffb-b886-4bf4bc011a9c'");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -33,6 +33,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
expected.Select("*")
|
||||
.From("[cmsContentType]")
|
||||
.InnerJoin("[umbracoNode]").On("[cmsContentType].[nodeId] = [umbracoNode].[id]")
|
||||
.Where("[umbracoNode].[nodeObjectType] = '4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e'");
|
||||
.Where("[umbracoNode].[nodeObjectType] = @0", new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e"));
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
@@ -30,6 +30,12 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
|
||||
Assert.That(sql.SQL, Is.EqualTo(expected.SQL));
|
||||
|
||||
Assert.AreEqual(expected.Arguments.Length, sql.Arguments.Length);
|
||||
for (int i = 0; i < expected.Arguments.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expected.Arguments[i], sql.Arguments[i]);
|
||||
}
|
||||
|
||||
Console.WriteLine(sql.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -6,12 +7,141 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Querying
|
||||
{
|
||||
[TestFixture]
|
||||
public class PetaPocoSqlTests : BaseUsingSqlCeSyntax
|
||||
{
|
||||
//x =>
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Starts_With_Additional_Parameters()
|
||||
{
|
||||
var content = new NodeDto() { NodeId = 123, Path = "-1,123" };
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Path.SqlStartsWith(content.Path, TextColumnType.NVarchar));
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[path]) LIKE upper(@0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(content.Path + "%", sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Starts_With_By_Variable()
|
||||
{
|
||||
var content = new NodeDto() {NodeId = 123, Path = "-1,123"};
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Path.StartsWith(content.Path) && x.NodeId != content.NodeId);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[path]) LIKE upper(@0) AND [umbracoNode].[id] <> @1)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(content.Path + "%", sql.Arguments[0]);
|
||||
Assert.AreEqual(content.NodeId, sql.Arguments[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Not_Starts_With()
|
||||
{
|
||||
var level = 1;
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Level == level && !x.Path.StartsWith("-20"));
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[level] = @0 AND NOT (upper([umbracoNode].[path]) LIKE upper(@1)))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(level, sql.Arguments[0]);
|
||||
Assert.AreEqual("-20%", sql.Arguments[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Equals_Clause()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text.Equals("Hello@world.com"));
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) = upper(@0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual("Hello@world.com", sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_False_Boolean()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => !x.Trashed);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (NOT ([umbracoNode].[trashed] = @0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(true, sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Boolean()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Trashed);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[trashed] = @0)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(true, sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_ToUpper()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text.ToUpper() == "hello".ToUpper());
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) = upper(@0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual("hello", sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_ToString()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text == 1.ToString());
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[text] = @0)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual("1", sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_With_Wildcard()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text.StartsWith("D"));
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE (upper([umbracoNode].[text]) LIKE upper(@0))", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual("D%", sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_Single_Constant()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.NodeId == 2);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[id] = @0)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(2, sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_And_Constant()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.NodeId != 2 && x.NodeId != 3);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[id] <> @0 AND [umbracoNode].[id] <> @1)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual(2, sql.Arguments[0]);
|
||||
Assert.AreEqual(3, sql.Arguments[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Where_Clause_Or_Constant()
|
||||
{
|
||||
var sql = new Sql("SELECT *").From<NodeDto>().Where<NodeDto>(x => x.Text == "hello" || x.NodeId == 3);
|
||||
|
||||
Assert.AreEqual("SELECT * FROM [umbracoNode] WHERE ([umbracoNode].[text] = @0 OR [umbracoNode].[id] = @1)", sql.SQL.Replace("\n", " "));
|
||||
Assert.AreEqual(2, sql.Arguments.Length);
|
||||
Assert.AreEqual("hello", sql.Arguments[0]);
|
||||
Assert.AreEqual(3, sql.Arguments[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Select_From_With_Type()
|
||||
@@ -78,7 +208,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
public void Can_Use_Where_Predicate()
|
||||
{
|
||||
var expected = new Sql();
|
||||
expected.Select("*").From("[cmsContent]").Where("[cmsContent].[nodeId] = 1045");
|
||||
expected.Select("*").From("[cmsContent]").Where("[cmsContent].[nodeId] = @0", 1045);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*").From<ContentDto>().Where<ContentDto>(x => x.NodeId == 1045);
|
||||
@@ -94,8 +224,8 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var expected = new Sql();
|
||||
expected.Select("*")
|
||||
.From("[cmsContent]")
|
||||
.Where("[cmsContent].[nodeId] = 1045")
|
||||
.Where("[cmsContent].[contentType] = 1050");
|
||||
.Where("[cmsContent].[nodeId] = @0", 1045)
|
||||
.Where("[cmsContent].[contentType] = @0", 1050);
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
|
||||
@@ -12,21 +12,7 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
[TestFixture]
|
||||
public class QueryBuilderTests : BaseUsingSqlCeSyntax
|
||||
{
|
||||
[Test]
|
||||
public void Dates_Formatted_Properly()
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select("*").From<DocumentDto>();
|
||||
|
||||
var dt = new DateTime(2013, 11, 21, 13, 25, 55);
|
||||
|
||||
var query = Query<IContent>.Builder.Where(x => x.ExpireDate <= dt);
|
||||
var translator = new SqlTranslator<IContent>(sql, query);
|
||||
|
||||
var result = translator.Translate();
|
||||
|
||||
Assert.IsTrue(result.SQL.Contains("[expireDate] <= '2013-11-21 13:25:55'"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Can_Build_StartsWith_Query_For_IContent()
|
||||
@@ -43,11 +29,15 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var result = translator.Translate();
|
||||
var strResult = result.SQL;
|
||||
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE (upper([umbracoNode].[path]) like '-1%')";
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE (upper([umbracoNode].[path]) LIKE upper(@0))";
|
||||
|
||||
// Assert
|
||||
Assert.That(strResult, Is.Not.Empty);
|
||||
Assert.That(strResult, Is.EqualTo(expectedResult));
|
||||
|
||||
Assert.AreEqual(1, result.Arguments.Length);
|
||||
Assert.AreEqual("-1%", sql.Arguments[0]);
|
||||
|
||||
Console.WriteLine(strResult);
|
||||
}
|
||||
|
||||
@@ -66,11 +56,15 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var result = translator.Translate();
|
||||
var strResult = result.SQL;
|
||||
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([umbracoNode].[parentID] = -1)";
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([umbracoNode].[parentID] = @0)";
|
||||
|
||||
// Assert
|
||||
Assert.That(strResult, Is.Not.Empty);
|
||||
Assert.That(strResult, Is.EqualTo(expectedResult));
|
||||
|
||||
Assert.AreEqual(1, result.Arguments.Length);
|
||||
Assert.AreEqual(-1, sql.Arguments[0]);
|
||||
|
||||
Console.WriteLine(strResult);
|
||||
}
|
||||
|
||||
@@ -89,11 +83,14 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var result = translator.Translate();
|
||||
var strResult = result.SQL;
|
||||
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([cmsContentType].[alias] = 'umbTextpage')";
|
||||
string expectedResult = "SELECT *\nFROM umbracoNode\nWHERE ([cmsContentType].[alias] = @0)";
|
||||
|
||||
// Assert
|
||||
Assert.That(strResult, Is.Not.Empty);
|
||||
Assert.That(strResult, Is.EqualTo(expectedResult));
|
||||
Assert.AreEqual(1, result.Arguments.Length);
|
||||
Assert.AreEqual("umbTextpage", sql.Arguments[0]);
|
||||
|
||||
Console.WriteLine(strResult);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,11 @@ namespace Umbraco.Tests.Persistence.SyntaxProvider
|
||||
FROM [cmsContentXml]
|
||||
INNER JOIN [umbracoNode]
|
||||
ON [cmsContentXml].[nodeId] = [umbracoNode].[id]
|
||||
WHERE ([umbracoNode].[nodeObjectType] = 'b796f64c-1f99-4ffb-b886-4bf4bc011a9c')) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "), sql.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "));
|
||||
WHERE ([umbracoNode].[nodeObjectType] = @0)) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "),
|
||||
sql.SQL.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "));
|
||||
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(mediaObjectType, sql.Arguments[0]);
|
||||
}
|
||||
|
||||
[NUnit.Framework.Ignore("This doesn't actually test anything")]
|
||||
|
||||
+16
-16
@@ -1,17 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for PluginTypeResolverTests
|
||||
/// </summary>
|
||||
internal static class PluginManagerExtensions
|
||||
{
|
||||
public static IEnumerable<Type> ResolveFindMeTypes(this PluginManager resolver)
|
||||
{
|
||||
return resolver.ResolveTypes<PluginManagerTests.IFindMe>();
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for PluginTypeResolverTests
|
||||
/// </summary>
|
||||
internal static class PluginManagerExtensions
|
||||
{
|
||||
public static IEnumerable<Type> ResolveFindMeTypes(this PluginManager resolver)
|
||||
{
|
||||
return resolver.ResolveTypes<PluginManagerTests.IFindMe>();
|
||||
}
|
||||
}
|
||||
}
|
||||
+387
-391
@@ -1,392 +1,388 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
using umbraco;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.MacroEngines;
|
||||
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
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//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[]
|
||||
{
|
||||
this.GetType().Assembly,
|
||||
typeof(ApplicationStartupHandler).Assembly,
|
||||
typeof(SqlCEHelper).Assembly,
|
||||
typeof(CMSNode).Assembly,
|
||||
typeof(System.Guid).Assembly,
|
||||
typeof(NUnit.Framework.Assert).Assembly,
|
||||
typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly,
|
||||
typeof(System.Xml.NameTable).Assembly,
|
||||
typeof(System.Configuration.GenericEnumConverter).Assembly,
|
||||
typeof(System.Web.SiteMap).Assembly,
|
||||
typeof(TabPage).Assembly,
|
||||
typeof(System.Web.Mvc.ActionResult).Assembly,
|
||||
typeof(TypeFinder).Assembly,
|
||||
typeof(ISqlHelper).Assembly,
|
||||
typeof(ICultureDictionary).Assembly,
|
||||
typeof(UmbracoContext).Assembly,
|
||||
typeof(BaseDataType).Assembly
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
PluginManager.Current = null;
|
||||
}
|
||||
|
||||
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 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);
|
||||
//}
|
||||
|
||||
////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 Detect_Legacy_Plugin_File_List()
|
||||
{
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
var manager = new PluginManager(false);
|
||||
var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
|
||||
|
||||
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>");
|
||||
|
||||
Assert.IsTrue(manager.DetectLegacyPluginListFile());
|
||||
|
||||
File.Delete(filePath);
|
||||
|
||||
//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>");
|
||||
|
||||
Assert.IsFalse(manager.DetectLegacyPluginListFile());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Create_Cached_Plugin_File()
|
||||
{
|
||||
var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) };
|
||||
|
||||
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);
|
||||
|
||||
var plugins = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
var diffType = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAttributedTypes);
|
||||
|
||||
Assert.IsTrue(plugins.Success);
|
||||
//this will be false since there is no cache of that type resolution kind
|
||||
Assert.IsFalse(diffType.Success);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[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 };
|
||||
|
||||
//Act
|
||||
var hash1 = PluginManager.GetFileHash(list1);
|
||||
var hash2 = PluginManager.GetFileHash(list2);
|
||||
var hash3 = PluginManager.GetFileHash(list3);
|
||||
|
||||
//Assert
|
||||
Assert.AreNotEqual(hash1, hash2);
|
||||
Assert.AreNotEqual(hash1, hash3);
|
||||
Assert.AreNotEqual(hash2, hash3);
|
||||
|
||||
Assert.AreEqual(hash1, PluginManager.GetFileHash(list1));
|
||||
}
|
||||
|
||||
[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_Assigned_Mappers()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveAssignedMapperTypes();
|
||||
Assert.AreEqual(22, foundTypes1.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Types()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
|
||||
Assert.AreEqual(2, foundTypes1.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Attributed_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveAttributedTrees();
|
||||
Assert.AreEqual(19, trees.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Actions()
|
||||
{
|
||||
var actions = PluginManager.Current.ResolveActions();
|
||||
Assert.AreEqual(36, actions.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveTrees();
|
||||
Assert.AreEqual(39, trees.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Applications()
|
||||
{
|
||||
var apps = PluginManager.Current.ResolveApplications();
|
||||
Assert.AreEqual(7, apps.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_DataTypes()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveDataTypes();
|
||||
Assert.AreEqual(35, 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(3, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_XsltExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveXsltExtensions();
|
||||
Assert.AreEqual(3, types.Count());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This demonstrates this issue: http://issues.umbraco.org/issue/U4-3505 - the TypeList was returning a list of assignable types
|
||||
/// not explicit types which is sort of ideal but is confusing so we'll do it the less confusing way.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TypeList_Resolves_Explicit_Types()
|
||||
{
|
||||
var types = new HashSet<PluginManager.TypeList>();
|
||||
|
||||
var propEditors = new PluginManager.TypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
propEditors.AddType(typeof(LabelPropertyEditor));
|
||||
types.Add(propEditors);
|
||||
|
||||
var found = types.SingleOrDefault(x => x.IsTypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
|
||||
|
||||
Assert.IsNotNull(found);
|
||||
|
||||
//This should not find a type list of this type
|
||||
var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList<IParameterEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
|
||||
|
||||
Assert.IsNull(shouldNotFind);
|
||||
}
|
||||
|
||||
[XsltExtension("Blah.Blah")]
|
||||
public class MyXsltExtension
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Umbraco.Web.BaseRest.RestExtension("Blah")]
|
||||
public class MyRestExtesion
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class FindMe1 : IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class FindMe2 : IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using SqlCE4Umbraco;
|
||||
using umbraco;
|
||||
using umbraco.businesslogic;
|
||||
using umbraco.cms.businesslogic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.editorControls;
|
||||
using umbraco.MacroEngines;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using umbraco.uicontrols;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class PluginManagerTests
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
TestHelper.SetupLog4NetForTests();
|
||||
|
||||
//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[]
|
||||
{
|
||||
this.GetType().Assembly,
|
||||
typeof(ApplicationStartupHandler).Assembly,
|
||||
typeof(SqlCEHelper).Assembly,
|
||||
typeof(CMSNode).Assembly,
|
||||
typeof(System.Guid).Assembly,
|
||||
typeof(NUnit.Framework.Assert).Assembly,
|
||||
typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly,
|
||||
typeof(System.Xml.NameTable).Assembly,
|
||||
typeof(System.Configuration.GenericEnumConverter).Assembly,
|
||||
typeof(System.Web.SiteMap).Assembly,
|
||||
typeof(TabPage).Assembly,
|
||||
typeof(System.Web.Mvc.ActionResult).Assembly,
|
||||
typeof(TypeFinder).Assembly,
|
||||
typeof(ISqlHelper).Assembly,
|
||||
typeof(ICultureDictionary).Assembly,
|
||||
typeof(UmbracoContext).Assembly,
|
||||
typeof(BaseDataType).Assembly
|
||||
};
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
PluginManager.Current = null;
|
||||
}
|
||||
|
||||
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 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);
|
||||
//}
|
||||
|
||||
////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 Detect_Legacy_Plugin_File_List()
|
||||
{
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
var manager = new PluginManager(false);
|
||||
var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
|
||||
|
||||
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>");
|
||||
|
||||
Assert.IsTrue(manager.DetectLegacyPluginListFile());
|
||||
|
||||
File.Delete(filePath);
|
||||
|
||||
//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>");
|
||||
|
||||
Assert.IsFalse(manager.DetectLegacyPluginListFile());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Create_Cached_Plugin_File()
|
||||
{
|
||||
var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) };
|
||||
|
||||
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);
|
||||
|
||||
var plugins = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
var diffType = manager.TryGetCachedPluginsFromFile<string>(PluginManager.TypeResolutionKind.FindAttributedTypes);
|
||||
|
||||
Assert.IsTrue(plugins.Success);
|
||||
//this will be false since there is no cache of that type resolution kind
|
||||
Assert.IsFalse(diffType.Success);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[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 };
|
||||
|
||||
//Act
|
||||
var hash1 = PluginManager.GetFileHash(list1);
|
||||
var hash2 = PluginManager.GetFileHash(list2);
|
||||
var hash3 = PluginManager.GetFileHash(list3);
|
||||
|
||||
//Assert
|
||||
Assert.AreNotEqual(hash1, hash2);
|
||||
Assert.AreNotEqual(hash1, hash3);
|
||||
Assert.AreNotEqual(hash2, hash3);
|
||||
|
||||
Assert.AreEqual(hash1, PluginManager.GetFileHash(list1));
|
||||
}
|
||||
|
||||
[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_Assigned_Mappers()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveAssignedMapperTypes();
|
||||
Assert.AreEqual(22, foundTypes1.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Types()
|
||||
{
|
||||
var foundTypes1 = PluginManager.Current.ResolveFindMeTypes();
|
||||
Assert.AreEqual(2, foundTypes1.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Attributed_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveAttributedTrees();
|
||||
Assert.AreEqual(19, trees.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Actions()
|
||||
{
|
||||
var actions = PluginManager.Current.ResolveActions();
|
||||
Assert.AreEqual(36, actions.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Trees()
|
||||
{
|
||||
var trees = PluginManager.Current.ResolveTrees();
|
||||
Assert.AreEqual(39, trees.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_Applications()
|
||||
{
|
||||
var apps = PluginManager.Current.ResolveApplications();
|
||||
Assert.AreEqual(7, apps.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_DataTypes()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveDataTypes();
|
||||
Assert.AreEqual(35, 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(3, types.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Resolves_XsltExtensions()
|
||||
{
|
||||
var types = PluginManager.Current.ResolveXsltExtensions();
|
||||
Assert.AreEqual(3, types.Count());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This demonstrates this issue: http://issues.umbraco.org/issue/U4-3505 - the TypeList was returning a list of assignable types
|
||||
/// not explicit types which is sort of ideal but is confusing so we'll do it the less confusing way.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TypeList_Resolves_Explicit_Types()
|
||||
{
|
||||
var types = new HashSet<PluginManager.TypeList>();
|
||||
|
||||
var propEditors = new PluginManager.TypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes);
|
||||
propEditors.AddType(typeof(LabelPropertyEditor));
|
||||
types.Add(propEditors);
|
||||
|
||||
var found = types.SingleOrDefault(x => x.IsTypeList<PropertyEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
|
||||
|
||||
Assert.IsNotNull(found);
|
||||
|
||||
//This should not find a type list of this type
|
||||
var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList<IParameterEditor>(PluginManager.TypeResolutionKind.FindAllTypes));
|
||||
|
||||
Assert.IsNull(shouldNotFind);
|
||||
}
|
||||
|
||||
[XsltExtension("Blah.Blah")]
|
||||
public class MyXsltExtension
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Umbraco.Web.BaseRest.RestExtension("Blah")]
|
||||
public class MyRestExtesion
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class FindMe1 : IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class FindMe2 : IFindMe
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+637
-640
File diff suppressed because it is too large
Load Diff
+71
-78
@@ -1,79 +1,72 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Data.Common;
|
||||
using System.Data.Odbc;
|
||||
using System.Data.OleDb;
|
||||
using System.Data.SqlClient;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.Scheduling;
|
||||
using UmbracoExamine;
|
||||
using UmbracoExamine.DataServices;
|
||||
using umbraco;
|
||||
using umbraco.presentation;
|
||||
using umbraco.presentation.nodeFactory;
|
||||
using umbraco.presentation.umbraco.Search;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for TypeHelper
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TypeHelperTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Is_Static_Class()
|
||||
{
|
||||
Assert.IsTrue(TypeHelper.IsStaticClass(typeof(TypeHelper)));
|
||||
Assert.IsFalse(TypeHelper.IsStaticClass(typeof(TypeHelperTests)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Find_Common_Base_Class()
|
||||
{
|
||||
var t1 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
|
||||
typeof (OdbcCommand),
|
||||
typeof (SqlCommand));
|
||||
Assert.IsFalse(t1.Success);
|
||||
|
||||
var t2 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
|
||||
typeof (OdbcCommand),
|
||||
typeof (SqlCommand),
|
||||
typeof (Component));
|
||||
Assert.IsTrue(t2.Success);
|
||||
Assert.AreEqual(typeof(Component), t2.Result);
|
||||
|
||||
var t3 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
|
||||
typeof (OdbcCommand),
|
||||
typeof (SqlCommand),
|
||||
typeof (Component),
|
||||
typeof (Component).BaseType);
|
||||
Assert.IsTrue(t3.Success);
|
||||
Assert.AreEqual(typeof(MarshalByRefObject), t3.Result);
|
||||
|
||||
var t4 = TypeHelper.GetLowestBaseType(typeof(OleDbCommand),
|
||||
typeof(OdbcCommand),
|
||||
typeof(SqlCommand),
|
||||
typeof(Component),
|
||||
typeof(Component).BaseType,
|
||||
typeof(int));
|
||||
Assert.IsFalse(t4.Success);
|
||||
|
||||
var t5 = TypeHelper.GetLowestBaseType(typeof(PropertyAliasDto));
|
||||
Assert.IsTrue(t5.Success);
|
||||
Assert.AreEqual(typeof(PropertyAliasDto), t5.Result);
|
||||
|
||||
var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
|
||||
typeof (Scheduler),
|
||||
typeof(CacheRefresherEventHandler));
|
||||
Assert.IsTrue(t6.Success);
|
||||
Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Data.Odbc;
|
||||
using System.Data.OleDb;
|
||||
using System.Data.SqlClient;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Cache;
|
||||
using Umbraco.Web.Scheduling;
|
||||
using UmbracoExamine.DataServices;
|
||||
|
||||
namespace Umbraco.Tests.Plugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for TypeHelper
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TypeHelperTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Is_Static_Class()
|
||||
{
|
||||
Assert.IsTrue(TypeHelper.IsStaticClass(typeof(TypeHelper)));
|
||||
Assert.IsFalse(TypeHelper.IsStaticClass(typeof(TypeHelperTests)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Find_Common_Base_Class()
|
||||
{
|
||||
var t1 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
|
||||
typeof (OdbcCommand),
|
||||
typeof (SqlCommand));
|
||||
Assert.IsFalse(t1.Success);
|
||||
|
||||
var t2 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
|
||||
typeof (OdbcCommand),
|
||||
typeof (SqlCommand),
|
||||
typeof (Component));
|
||||
Assert.IsTrue(t2.Success);
|
||||
Assert.AreEqual(typeof(Component), t2.Result);
|
||||
|
||||
var t3 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand),
|
||||
typeof (OdbcCommand),
|
||||
typeof (SqlCommand),
|
||||
typeof (Component),
|
||||
typeof (Component).BaseType);
|
||||
Assert.IsTrue(t3.Success);
|
||||
Assert.AreEqual(typeof(MarshalByRefObject), t3.Result);
|
||||
|
||||
var t4 = TypeHelper.GetLowestBaseType(typeof(OleDbCommand),
|
||||
typeof(OdbcCommand),
|
||||
typeof(SqlCommand),
|
||||
typeof(Component),
|
||||
typeof(Component).BaseType,
|
||||
typeof(int));
|
||||
Assert.IsFalse(t4.Success);
|
||||
|
||||
var t5 = TypeHelper.GetLowestBaseType(typeof(PropertyAliasDto));
|
||||
Assert.IsTrue(t5.Success);
|
||||
Assert.AreEqual(typeof(PropertyAliasDto), t5.Result);
|
||||
|
||||
var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler),
|
||||
typeof (Scheduler),
|
||||
typeof(CacheRefresherEventHandler));
|
||||
Assert.IsTrue(t6.Success);
|
||||
Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -92,9 +92,9 @@ namespace Umbraco.Tests.PublishedCache
|
||||
|
||||
_umbracoContext = new UmbracoContext(
|
||||
_httpContextFactory.HttpContext,
|
||||
ApplicationContext.Current,
|
||||
new PublishedCaches(cache, new PublishedMediaCache()),
|
||||
new WebSecurity(_httpContextFactory.HttpContext, ApplicationContext.Current));
|
||||
ApplicationContext,
|
||||
new PublishedCaches(cache, new PublishedMediaCache(ApplicationContext)),
|
||||
new WebSecurity(_httpContextFactory.HttpContext, ApplicationContext));
|
||||
|
||||
_cache = _umbracoContext.ContentCache;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.PublishedCache
|
||||
var mChild2 = global::umbraco.cms.businesslogic.media.Media.MakeNew("Child2", mType, user, mRoot2.Id);
|
||||
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application), ctx);
|
||||
var roots = cache.GetAtRoot();
|
||||
Assert.AreEqual(2, roots.Count());
|
||||
Assert.IsTrue(roots.Select(x => x.Id).ContainsAll(new[] {mRoot1.Id, mRoot2.Id}));
|
||||
@@ -126,6 +126,8 @@ namespace Umbraco.Tests.PublishedCache
|
||||
[Test]
|
||||
public void Convert_From_Search_Result()
|
||||
{
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
|
||||
var result = new SearchResult()
|
||||
{
|
||||
Id = 1234,
|
||||
@@ -144,7 +146,7 @@ namespace Umbraco.Tests.PublishedCache
|
||||
result.Fields.Add("updateDate", "2012-07-16T10:34:09");
|
||||
result.Fields.Add("writerName", "Shannon");
|
||||
|
||||
var store = new PublishedMediaCache();
|
||||
var store = new PublishedMediaCache(ctx.Application);
|
||||
var doc = store.ConvertFromSearchResult(result);
|
||||
|
||||
DoAssert(doc, 1234, 0, 0, "", "Image", 0, "Shannon", "", 0, 0, "-1,1234", default(DateTime), DateTime.Parse("2012-07-16T10:34:09"), 2);
|
||||
@@ -154,9 +156,11 @@ namespace Umbraco.Tests.PublishedCache
|
||||
[Test]
|
||||
public void Convert_From_XPath_Navigator()
|
||||
{
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
|
||||
var xmlDoc = GetMediaXml();
|
||||
var navigator = xmlDoc.SelectSingleNode("/root/Image").CreateNavigator();
|
||||
var cache = new PublishedMediaCache();
|
||||
var cache = new PublishedMediaCache(ctx.Application);
|
||||
var doc = cache.ConvertFromXPathNavigator(navigator);
|
||||
|
||||
DoAssert(doc, 2000, 0, 2, "image1", "Image", 2044, "Shannon", "Shannon2", 22, 33, "-1,2000", DateTime.Parse("2012-06-12T14:13:17"), DateTime.Parse("2012-07-20T18:50:43"), 1);
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
});
|
||||
|
||||
PublishedCachesResolver.Current = new PublishedCachesResolver(new PublishedCaches(
|
||||
new PublishedContentCache(), new PublishedMediaCache()));
|
||||
new PublishedContentCache(), new PublishedMediaCache(ApplicationContext)));
|
||||
|
||||
if (PublishedContentModelFactoryResolver.HasCurrent == false)
|
||||
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver();
|
||||
|
||||
@@ -11,6 +11,7 @@ using Examine.LuceneEngine;
|
||||
using Examine.LuceneEngine.Providers;
|
||||
using Lucene.Net.Analysis.Standard;
|
||||
using Lucene.Net.Store;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -60,7 +61,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
internal static IPublishedContent GetNode(int id, UmbracoContext umbracoContext)
|
||||
{
|
||||
var ctx = umbracoContext;
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application), ctx);
|
||||
var doc = cache.GetById(id);
|
||||
Assert.IsNotNull(doc);
|
||||
return doc;
|
||||
@@ -112,7 +113,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = cache.GetById(1111);
|
||||
@@ -141,7 +142,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//ensure it is found
|
||||
var publishedMedia = cache.GetById(3113);
|
||||
@@ -181,7 +182,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = cache.GetById(1111);
|
||||
@@ -203,7 +204,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = cache.GetById(1111);
|
||||
@@ -225,7 +226,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = cache.GetById(1111);
|
||||
@@ -247,7 +248,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = cache.GetById(3113);
|
||||
@@ -266,7 +267,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
indexer.RebuildIndex();
|
||||
var ctx = GetUmbracoContext("/test", 1234);
|
||||
var searcher = IndexInitializer.GetUmbracoSearcher(luceneDir);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(searcher, indexer), ctx);
|
||||
var cache = new ContextualPublishedMediaCache(new PublishedMediaCache(ctx.Application, searcher, indexer), ctx);
|
||||
|
||||
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
|
||||
var publishedMedia = cache.GetById(3113);
|
||||
@@ -412,6 +413,100 @@ namespace Umbraco.Tests.PublishedContent
|
||||
Assert.IsTrue(publishedSubChild1.AncestorsOrSelf().Select(x => x.Id).ContainsAll(
|
||||
new[] { mSubChild1.Id, mChild1.Id, mRoot.Id }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Convert_From_Legacy_Xml()
|
||||
{
|
||||
var config = SettingsForTests.GenerateMockSettings();
|
||||
|
||||
var contentMock = Mock.Get(config.Content);
|
||||
contentMock.Setup(x => x.UseLegacyXmlSchema).Returns(true);
|
||||
|
||||
SettingsForTests.ConfigureSettings(config);
|
||||
|
||||
var nodeId = 2112;
|
||||
|
||||
var xml = XElement.Parse(@"<node id=""2112"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd39"" parentID=""2222"" level=""3"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""1"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Sam's Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112"">
|
||||
<data alias=""umbracoFile""><![CDATA[/media/1234/blah.pdf]]></data>
|
||||
<data alias=""umbracoWidth"">115</data>
|
||||
<data alias=""umbracoHeight"">268</data>
|
||||
<data alias=""umbracoBytes"">10726</data>
|
||||
<data alias=""umbracoExtension"">jpg</data>
|
||||
<node id=""3113"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd33"" parentID=""2112"" level=""4"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""2"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Another Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112,3113"">
|
||||
<data alias=""umbracoFile""><![CDATA[/media/1234/blah.pdf]]></data>
|
||||
<data alias=""umbracoWidth"">115</data>
|
||||
<data alias=""umbracoHeight"">268</data>
|
||||
<data alias=""umbracoBytes"">10726</data>
|
||||
<data alias=""umbracoExtension"">jpg</data>
|
||||
</node>
|
||||
</node>");
|
||||
var node = xml.DescendantsAndSelf("node").Single(x => (int) x.Attribute("id") == nodeId);
|
||||
|
||||
var publishedMedia = new PublishedMediaCache(ApplicationContext);
|
||||
|
||||
var nav = node.CreateNavigator();
|
||||
|
||||
var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/node"), nodeId);
|
||||
|
||||
Assert.AreEqual(nodeId, converted.Id);
|
||||
Assert.AreEqual(3, converted.Level);
|
||||
Assert.AreEqual(1, converted.SortOrder);
|
||||
Assert.AreEqual("Sam's Umbraco Image", converted.Name);
|
||||
Assert.AreEqual("-1,1111,2222,2112", converted.Path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Convert_From_Standard_Xml()
|
||||
{
|
||||
var config = SettingsForTests.GenerateMockSettings();
|
||||
|
||||
var contentMock = Mock.Get(config.Content);
|
||||
contentMock.Setup(x => x.UseLegacyXmlSchema).Returns(true);
|
||||
|
||||
SettingsForTests.ConfigureSettings(config);
|
||||
|
||||
var nodeId = 2112;
|
||||
|
||||
var xml = XElement.Parse(@"<Image id=""2112"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd39"" parentID=""2222"" level=""3"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""1"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Sam's Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112"" isDoc="""">
|
||||
<umbracoFile><![CDATA[/media/1234/blah.pdf]]></umbracoFile>
|
||||
<umbracoWidth>115</umbracoWidth>
|
||||
<umbracoHeight>268</umbracoHeight>
|
||||
<umbracoBytes>10726</umbracoBytes>
|
||||
<umbracoExtension>jpg</umbracoExtension>
|
||||
<Image id=""3113"" version=""5b3e46ab-3e37-4cfa-ab70-014234b5bd33"" parentID=""2112"" level=""4"" writerID=""0"" nodeType=""1032"" template=""0"" sortOrder=""2"" createDate=""2010-05-19T17:32:46"" updateDate=""2010-05-19T17:32:46"" nodeName=""Another Umbraco Image"" urlName=""acnestressscrub"" writerName=""Administrator"" nodeTypeAlias=""Image"" path=""-1,1111,2222,2112,3113"" isDoc="""">
|
||||
<umbracoFile><![CDATA[/media/1234/blah.pdf]]></umbracoFile>
|
||||
<umbracoWidth>115</umbracoWidth>
|
||||
<umbracoHeight>268</umbracoHeight>
|
||||
<umbracoBytes>10726</umbracoBytes>
|
||||
<umbracoExtension>jpg</umbracoExtension>
|
||||
</Image>
|
||||
</Image>");
|
||||
var node = xml.DescendantsAndSelf("Image").Single(x => (int)x.Attribute("id") == nodeId);
|
||||
|
||||
var publishedMedia = new PublishedMediaCache(ApplicationContext);
|
||||
|
||||
var nav = node.CreateNavigator();
|
||||
|
||||
var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/Image"), nodeId);
|
||||
|
||||
Assert.AreEqual(nodeId, converted.Id);
|
||||
Assert.AreEqual(3, converted.Level);
|
||||
Assert.AreEqual(1, converted.SortOrder);
|
||||
Assert.AreEqual("Sam's Umbraco Image", converted.Name);
|
||||
Assert.AreEqual("-1,1111,2222,2112", converted.Path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Detects_Error_In_Xml()
|
||||
{
|
||||
var errorXml = new XElement("error", string.Format("No media is maching '{0}'", 1234));
|
||||
var nav = errorXml.CreateNavigator();
|
||||
|
||||
var publishedMedia = new PublishedMediaCache(ApplicationContext);
|
||||
var converted = publishedMedia.ConvertFromXPathNodeIterator(nav.Select("/"), 1234);
|
||||
|
||||
Assert.IsNull(converted);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Scheduling;
|
||||
|
||||
namespace Umbraco.Tests.Scheduling
|
||||
{
|
||||
[TestFixture]
|
||||
public class BackgroundTaskRunnerTests
|
||||
{
|
||||
|
||||
|
||||
[Test]
|
||||
public void Startup_And_Shutdown()
|
||||
{
|
||||
BackgroundTaskRunner<IBackgroundTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<IBackgroundTask>(true, true))
|
||||
{
|
||||
tManager.StartUp();
|
||||
}
|
||||
|
||||
NUnit.Framework.Assert.IsFalse(tManager.IsRunning);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Startup_Starts_Automatically()
|
||||
{
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
|
||||
{
|
||||
tManager.Add(new MyTask());
|
||||
NUnit.Framework.Assert.IsTrue(tManager.IsRunning);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Task_Runs()
|
||||
{
|
||||
var myTask = new MyTask();
|
||||
var waitHandle = new ManualResetEvent(false);
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
|
||||
{
|
||||
tManager.TaskCompleted += (sender, task) => waitHandle.Set();
|
||||
|
||||
tManager.Add(myTask);
|
||||
|
||||
//wait for ITasks to complete
|
||||
waitHandle.WaitOne();
|
||||
|
||||
NUnit.Framework.Assert.IsTrue(myTask.Ended != default(DateTime));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Many_Tasks_Run()
|
||||
{
|
||||
var tasks = new Dictionary<BaseTask, ManualResetEvent>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
tasks.Add(new MyTask(), new ManualResetEvent(false));
|
||||
}
|
||||
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
|
||||
{
|
||||
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
|
||||
|
||||
tasks.ForEach(t => tManager.Add(t.Key));
|
||||
|
||||
//wait for all ITasks to complete
|
||||
WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
NUnit.Framework.Assert.IsTrue(task.Key.Ended != default(DateTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Tasks_Can_Keep_Being_Added_And_Will_Execute()
|
||||
{
|
||||
Func<Dictionary<BaseTask, ManualResetEvent>> getTasks = () =>
|
||||
{
|
||||
var newTasks = new Dictionary<BaseTask, ManualResetEvent>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
newTasks.Add(new MyTask(), new ManualResetEvent(false));
|
||||
}
|
||||
return newTasks;
|
||||
};
|
||||
|
||||
IDictionary<BaseTask, ManualResetEvent> tasks = getTasks();
|
||||
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
|
||||
{
|
||||
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
|
||||
|
||||
//execute first batch
|
||||
tasks.ForEach(t => tManager.Add(t.Key));
|
||||
|
||||
//wait for all ITasks to complete
|
||||
WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
NUnit.Framework.Assert.IsTrue(task.Key.Ended != default(DateTime));
|
||||
}
|
||||
|
||||
//execute another batch after a bit
|
||||
Thread.Sleep(2000);
|
||||
|
||||
tasks = getTasks();
|
||||
tasks.ForEach(t => tManager.Add(t.Key));
|
||||
|
||||
//wait for all ITasks to complete
|
||||
WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
NUnit.Framework.Assert.IsTrue(task.Key.Ended != default(DateTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Task_Queue_Will_Be_Completed_Before_Shutdown()
|
||||
{
|
||||
var tasks = new Dictionary<BaseTask, ManualResetEvent>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
tasks.Add(new MyTask(), new ManualResetEvent(false));
|
||||
}
|
||||
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(true, true))
|
||||
{
|
||||
tManager.TaskCompleted += (sender, task) => tasks[task.Task].Set();
|
||||
|
||||
tasks.ForEach(t => tManager.Add(t.Key));
|
||||
|
||||
////wait for all ITasks to complete
|
||||
//WaitHandle.WaitAll(tasks.Values.Select(x => (WaitHandle)x).ToArray());
|
||||
|
||||
tManager.Stop(false);
|
||||
//immediate stop will block until complete - but since we are running on
|
||||
// a single thread this doesn't really matter as the above will just process
|
||||
// until complete.
|
||||
tManager.Stop(true);
|
||||
|
||||
NUnit.Framework.Assert.AreEqual(0, tManager.TaskCount);
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: These tests work in .Net 4.5 but in this current version we don't have the correct
|
||||
// async/await signatures with GetAwaiter, so am just commenting these out in this version
|
||||
|
||||
[Test]
|
||||
public async void Non_Persistent_Runner_Will_End_After_Queue_Empty()
|
||||
{
|
||||
var tasks = new List<BaseTask>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
tasks.Add(new MyTask());
|
||||
}
|
||||
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(persistentThread: false, dedicatedThread:true))
|
||||
{
|
||||
tasks.ForEach(t => tManager.Add(t));
|
||||
|
||||
//wait till the thread is done
|
||||
await tManager;
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
Assert.IsTrue(task.Ended != default(DateTime));
|
||||
}
|
||||
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus);
|
||||
Assert.IsFalse(tManager.IsRunning);
|
||||
Assert.IsFalse(tManager.IsDisposed);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async void Non_Persistent_Runner_Will_Start_New_Threads_When_Required()
|
||||
{
|
||||
Func<List<BaseTask>> getTasks = () =>
|
||||
{
|
||||
var newTasks = new List<BaseTask>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
newTasks.Add(new MyTask());
|
||||
}
|
||||
return newTasks;
|
||||
};
|
||||
|
||||
List<BaseTask> tasks = getTasks();
|
||||
|
||||
BackgroundTaskRunner<BaseTask> tManager;
|
||||
using (tManager = new BackgroundTaskRunner<BaseTask>(persistentThread: false, dedicatedThread: true))
|
||||
{
|
||||
tasks.ForEach(t => tManager.Add(t));
|
||||
|
||||
//wait till the thread is done
|
||||
await tManager;
|
||||
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus);
|
||||
Assert.IsFalse(tManager.IsRunning);
|
||||
Assert.IsFalse(tManager.IsDisposed);
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
Assert.IsTrue(task.Ended != default(DateTime));
|
||||
}
|
||||
|
||||
//create more tasks
|
||||
tasks = getTasks();
|
||||
|
||||
//add more tasks
|
||||
tasks.ForEach(t => tManager.Add(t));
|
||||
|
||||
//wait till the thread is done
|
||||
await tManager;
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
Assert.IsTrue(task.Ended != default(DateTime));
|
||||
}
|
||||
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, tManager.TaskStatus);
|
||||
Assert.IsFalse(tManager.IsRunning);
|
||||
Assert.IsFalse(tManager.IsDisposed);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyTask : BaseTask
|
||||
{
|
||||
public MyTask()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseTask : IBackgroundTask
|
||||
{
|
||||
public Guid UniqueId { get; protected set; }
|
||||
|
||||
public abstract void Run();
|
||||
public abstract void Cancel();
|
||||
|
||||
public DateTime Queued { get; set; }
|
||||
public DateTime Started { get; set; }
|
||||
public DateTime Ended { get; set; }
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Ended = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ServerEnvironmentHelperTests
|
||||
{
|
||||
[Test]
|
||||
public void Get_Base_Url_Single_Server_Orig_Request_Url_No_SSL()
|
||||
{
|
||||
var appContext = new ApplicationContext(null)
|
||||
{
|
||||
OriginalRequestUrl = "test.com"
|
||||
};
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false");
|
||||
|
||||
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
|
||||
appContext,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>()));
|
||||
|
||||
|
||||
Assert.AreEqual("http://test.com/", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Base_Url_Single_Server_Orig_Request_Url_With_SSL()
|
||||
{
|
||||
var appContext = new ApplicationContext(null)
|
||||
{
|
||||
OriginalRequestUrl = "test.com"
|
||||
};
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
|
||||
appContext,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>()));
|
||||
|
||||
|
||||
Assert.AreEqual("https://test.com/", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Base_Url_Single_Server_Via_Config_Url_No_SSL()
|
||||
{
|
||||
var appContext = new ApplicationContext(null);
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false");
|
||||
|
||||
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
|
||||
appContext,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world")));
|
||||
|
||||
|
||||
Assert.AreEqual("http://mycoolhost.com/hello/world/", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Base_Url_Single_Server_Via_Config_Url_With_SSL()
|
||||
{
|
||||
var appContext = new ApplicationContext(null);
|
||||
|
||||
ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true");
|
||||
|
||||
var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl(
|
||||
appContext,
|
||||
Mock.Of<IUmbracoSettingsSection>(
|
||||
section =>
|
||||
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Servers == Enumerable.Empty<IServer>())
|
||||
&& section.ScheduledTasks == Mock.Of<IScheduledTasksSection>(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world")));
|
||||
|
||||
|
||||
Assert.AreEqual("https://mycoolhost.com/hello/world/", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,30 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(entities.Any(x => x.Trashed), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Children_By_ParentId()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
var entities = service.GetChildren(folderId);
|
||||
|
||||
Assert.That(entities.Any(), Is.True);
|
||||
Assert.That(entities.Count(), Is.EqualTo(3));
|
||||
Assert.That(entities.Any(x => x.Trashed), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Descendants_By_ParentId()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
var entities = service.GetDescendents(folderId);
|
||||
|
||||
Assert.That(entities.Any(), Is.True);
|
||||
Assert.That(entities.Count(), Is.EqualTo(4));
|
||||
Assert.That(entities.Any(x => x.Trashed), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Throws_When_Getting_All_With_Invalid_Type()
|
||||
{
|
||||
@@ -129,7 +153,7 @@ namespace Umbraco.Tests.Services
|
||||
var entities = service.GetAll(UmbracoObjectTypes.Media).ToArray();
|
||||
|
||||
Assert.That(entities.Any(), Is.True);
|
||||
Assert.That(entities.Count(), Is.EqualTo(3));
|
||||
Assert.That(entities.Count(), Is.EqualTo(5));
|
||||
|
||||
Assert.That(
|
||||
entities.Any(
|
||||
@@ -150,6 +174,8 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
private static bool _isSetup = false;
|
||||
|
||||
private int folderId;
|
||||
|
||||
public override void CreateTestData()
|
||||
{
|
||||
if (_isSetup == false)
|
||||
@@ -160,8 +186,9 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
//Create and Save folder-Media -> 1050
|
||||
var folderMediaType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var folder = MockedMedia.CreateMediaFolder(folderMediaType, -1);
|
||||
var folder = MockedMedia.CreateMediaFolder(folderMediaType, -1);
|
||||
ServiceContext.MediaService.Save(folder, 0);
|
||||
folderId = folder.Id;
|
||||
|
||||
//Create and Save image-Media -> 1051
|
||||
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
|
||||
@@ -172,6 +199,12 @@ namespace Umbraco.Tests.Services
|
||||
var fileMediaType = ServiceContext.ContentTypeService.GetMediaType(1033);
|
||||
var file = MockedMedia.CreateMediaFile(fileMediaType, folder.Id);
|
||||
ServiceContext.MediaService.Save(file, 0);
|
||||
|
||||
var subfolder = MockedMedia.CreateMediaFolder(folderMediaType, folder.Id);
|
||||
ServiceContext.MediaService.Save(subfolder, 0);
|
||||
var subfolder2 = MockedMedia.CreateMediaFolder(folderMediaType, subfolder.Id);
|
||||
ServiceContext.MediaService.Save(subfolder2, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -94,15 +94,20 @@ namespace Umbraco.Tests.Services
|
||||
ServiceContext.MemberTypeService.Save(memberType);
|
||||
IMember member = MockedMember.CreateSimpleMember(memberType, "test", "test@test.com", "pass", "test");
|
||||
ServiceContext.MemberService.Save(member);
|
||||
//need to test with '@' symbol in the lookup
|
||||
IMember member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2@test.com");
|
||||
ServiceContext.MemberService.Save(member2);
|
||||
|
||||
ServiceContext.MemberService.AddRole("MyTestRole1");
|
||||
ServiceContext.MemberService.AddRole("MyTestRole2");
|
||||
ServiceContext.MemberService.AddRole("MyTestRole3");
|
||||
ServiceContext.MemberService.AssignRoles(new[] { member.Id }, new[] { "MyTestRole1", "MyTestRole2" });
|
||||
ServiceContext.MemberService.AssignRoles(new[] { member.Id, member2.Id }, new[] { "MyTestRole1", "MyTestRole2" });
|
||||
|
||||
var memberRoles = ServiceContext.MemberService.GetAllRoles("test");
|
||||
|
||||
Assert.AreEqual(2, memberRoles.Count());
|
||||
|
||||
var memberRoles2 = ServiceContext.MemberService.GetAllRoles("test2@test.com");
|
||||
Assert.AreEqual(2, memberRoles2.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -325,9 +330,12 @@ namespace Umbraco.Tests.Services
|
||||
ServiceContext.MemberTypeService.Save(memberType);
|
||||
IMember member = MockedMember.CreateSimpleMember(memberType, "test", "test@test.com", "pass", "test");
|
||||
ServiceContext.MemberService.Save(member);
|
||||
IMember member2 = MockedMember.CreateSimpleMember(memberType, "test", "test2@test.com", "pass", "test2@test.com");
|
||||
ServiceContext.MemberService.Save(member2);
|
||||
|
||||
Assert.IsTrue(ServiceContext.MemberService.Exists("test"));
|
||||
Assert.IsFalse(ServiceContext.MemberService.Exists("notFound"));
|
||||
Assert.IsTrue(ServiceContext.MemberService.Exists("test2@test.com"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -130,9 +130,10 @@ namespace Umbraco.Tests.Services
|
||||
var userType = MockedUserType.CreateUserType();
|
||||
ServiceContext.UserService.SaveUserType(userType);
|
||||
var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType);
|
||||
|
||||
var user2 = ServiceContext.UserService.CreateUserWithIdentity("john2@umbraco.io", "john2@umbraco.io", userType);
|
||||
Assert.IsTrue(ServiceContext.UserService.Exists("JohnDoe"));
|
||||
Assert.IsFalse(ServiceContext.UserService.Exists("notFound"));
|
||||
Assert.IsTrue(ServiceContext.UserService.Exists("john2@umbraco.io"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -356,7 +356,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
var ctx = new UmbracoContext(
|
||||
httpContext,
|
||||
ApplicationContext,
|
||||
new PublishedCaches(cache, new PublishedMediaCache()),
|
||||
new PublishedCaches(cache, new PublishedMediaCache(ApplicationContext)),
|
||||
new WebSecurity(httpContext, ApplicationContext));
|
||||
|
||||
if (setSingleton)
|
||||
|
||||
@@ -19,10 +19,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
[SetUp]
|
||||
public virtual void Initialize()
|
||||
{
|
||||
using (DisposableTimer.TraceDuration<BaseUmbracoConfigurationTest>("init"))
|
||||
{
|
||||
SettingsForTests.Reset();
|
||||
}
|
||||
SettingsForTests.Reset();
|
||||
|
||||
}
|
||||
|
||||
@@ -30,10 +27,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
public virtual void TearDown()
|
||||
{
|
||||
//reset settings
|
||||
using (DisposableTimer.TraceDuration<BaseUmbracoConfigurationTest>("teardown"))
|
||||
{
|
||||
SettingsForTests.Reset();
|
||||
}
|
||||
SettingsForTests.Reset();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+123
-127
@@ -1,127 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.presentation.Trees;
|
||||
|
||||
namespace Umbraco.Tests.Trees
|
||||
{
|
||||
[TestFixture]
|
||||
public class BaseContentTreeTests
|
||||
{
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
BaseTree.AfterTreeRender -= EventHandler;
|
||||
BaseTree.BeforeTreeRender -= EventHandler;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Run_Optimized()
|
||||
{
|
||||
var tree1 = new MyOptimizedContentTree1("content");
|
||||
var tree2 = new MyOptimizedContentTree2("content");
|
||||
|
||||
Assert.IsTrue(tree1.UseOptimizedRendering);
|
||||
Assert.IsTrue(tree2.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_AfterRender()
|
||||
{
|
||||
var tree = new MyOptimizedContentTree1("content");
|
||||
|
||||
BaseTree.AfterTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_BeforeRender()
|
||||
{
|
||||
var tree = new MyOptimizedContentTree1("content");
|
||||
|
||||
BaseTree.BeforeTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Overriden_Method()
|
||||
{
|
||||
var tree = new MyNotOptimizedContentTree("content");
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//optimized because we are not overriding OnRenderNode
|
||||
public class MyOptimizedContentTree1 : BaseContentTree
|
||||
{
|
||||
public MyOptimizedContentTree1(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class MyOptimizedContentTree2 : BaseContentTree
|
||||
{
|
||||
public MyOptimizedContentTree2(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool LoadMinimalDocument
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//even if we override it will still be optimized because of the LoadMinimalDocument flag
|
||||
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
|
||||
{
|
||||
base.OnRenderNode(ref xNode, doc);
|
||||
}
|
||||
}
|
||||
|
||||
public class MyNotOptimizedContentTree : BaseContentTree
|
||||
{
|
||||
public MyNotOptimizedContentTree(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override bool LoadMinimalDocument
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
|
||||
{
|
||||
base.OnRenderNode(ref xNode, doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.presentation.Trees;
|
||||
|
||||
namespace Umbraco.Tests.TreesAndSections
|
||||
{
|
||||
[TestFixture]
|
||||
public class BaseContentTreeTests
|
||||
{
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
BaseTree.AfterTreeRender -= EventHandler;
|
||||
BaseTree.BeforeTreeRender -= EventHandler;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Run_Optimized()
|
||||
{
|
||||
var tree1 = new MyOptimizedContentTree1("content");
|
||||
var tree2 = new MyOptimizedContentTree2("content");
|
||||
|
||||
Assert.IsTrue(tree1.UseOptimizedRendering);
|
||||
Assert.IsTrue(tree2.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_AfterRender()
|
||||
{
|
||||
var tree = new MyOptimizedContentTree1("content");
|
||||
|
||||
BaseTree.AfterTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_BeforeRender()
|
||||
{
|
||||
var tree = new MyOptimizedContentTree1("content");
|
||||
|
||||
BaseTree.BeforeTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Overriden_Method()
|
||||
{
|
||||
var tree = new MyNotOptimizedContentTree("content");
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//optimized because we are not overriding OnRenderNode
|
||||
public class MyOptimizedContentTree1 : BaseContentTree
|
||||
{
|
||||
public MyOptimizedContentTree1(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class MyOptimizedContentTree2 : BaseContentTree
|
||||
{
|
||||
public MyOptimizedContentTree2(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool LoadMinimalDocument
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//even if we override it will still be optimized because of the LoadMinimalDocument flag
|
||||
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
|
||||
{
|
||||
base.OnRenderNode(ref xNode, doc);
|
||||
}
|
||||
}
|
||||
|
||||
public class MyNotOptimizedContentTree : BaseContentTree
|
||||
{
|
||||
public MyNotOptimizedContentTree(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override bool LoadMinimalDocument
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc)
|
||||
{
|
||||
base.OnRenderNode(ref xNode, doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
+64
-64
@@ -1,65 +1,65 @@
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.presentation.Trees;
|
||||
|
||||
namespace Umbraco.Tests.Trees
|
||||
{
|
||||
[TestFixture]
|
||||
public class BaseMediaTreeTests
|
||||
{
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
BaseTree.AfterTreeRender -= EventHandler;
|
||||
BaseTree.BeforeTreeRender -= EventHandler;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Run_Optimized()
|
||||
{
|
||||
var tree = new MyOptimizedMediaTree("media");
|
||||
|
||||
Assert.IsTrue(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_AfterRender()
|
||||
{
|
||||
var tree = new MyOptimizedMediaTree("media");
|
||||
|
||||
BaseTree.AfterTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_BeforeRender()
|
||||
{
|
||||
var tree = new MyOptimizedMediaTree("media");
|
||||
|
||||
BaseTree.BeforeTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class MyOptimizedMediaTree : BaseMediaTree
|
||||
{
|
||||
public MyOptimizedMediaTree(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
using NUnit.Framework;
|
||||
using umbraco.cms.presentation.Trees;
|
||||
|
||||
namespace Umbraco.Tests.TreesAndSections
|
||||
{
|
||||
[TestFixture]
|
||||
public class BaseMediaTreeTests
|
||||
{
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
BaseTree.AfterTreeRender -= EventHandler;
|
||||
BaseTree.BeforeTreeRender -= EventHandler;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Run_Optimized()
|
||||
{
|
||||
var tree = new MyOptimizedMediaTree("media");
|
||||
|
||||
Assert.IsTrue(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_AfterRender()
|
||||
{
|
||||
var tree = new MyOptimizedMediaTree("media");
|
||||
|
||||
BaseTree.AfterTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Not_Optimized_Events_BeforeRender()
|
||||
{
|
||||
var tree = new MyOptimizedMediaTree("media");
|
||||
|
||||
BaseTree.BeforeTreeRender += EventHandler;
|
||||
|
||||
Assert.IsFalse(tree.UseOptimizedRendering);
|
||||
}
|
||||
|
||||
private void EventHandler(object sender, TreeEventArgs treeEventArgs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class MyOptimizedMediaTree : BaseMediaTree
|
||||
{
|
||||
public MyOptimizedMediaTree(string application)
|
||||
: base(application)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void CreateRootNode(ref XmlTreeNode rootNode)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -276,7 +276,7 @@
|
||||
<Compile Include="Controllers\WebApiEditors\FilterAllowedOutgoingContentAttributeTests.cs" />
|
||||
<Compile Include="Controllers\WebApiEditors\MediaControllerUnitTests.cs" />
|
||||
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
|
||||
<Compile Include="Dynamics\QueryableExtensionTests.cs" />
|
||||
<Compile Include="DynamicsAndReflection\QueryableExtensionTests.cs" />
|
||||
<Compile Include="DynamicsAndReflection\ExtensionMethodFinderTests.cs" />
|
||||
<Compile Include="DynamicsAndReflection\ReflectionTests.cs" />
|
||||
<Compile Include="Integration\CreateContent.cs" />
|
||||
@@ -311,6 +311,8 @@
|
||||
<Compile Include="PublishedContent\StronglyTypedModels\Textpage.cs" />
|
||||
<Compile Include="PublishedContent\StronglyTypedModels\TypedModelBase.cs" />
|
||||
<Compile Include="PublishedContent\StronglyTypedModels\UmbracoTemplatePage`T.cs" />
|
||||
<Compile Include="Scheduling\BackgroundTaskRunnerTests.cs" />
|
||||
<Compile Include="ServerEnvironmentHelperTests.cs" />
|
||||
<Compile Include="Services\TagServiceTests.cs" />
|
||||
<Compile Include="Services\LocalizationServiceTests.cs" />
|
||||
<Compile Include="Resolvers\XsltExtensionsResolverTests.cs" />
|
||||
@@ -375,7 +377,7 @@
|
||||
<Compile Include="PublishedContent\PublishedContentTests.cs" />
|
||||
<Compile Include="PublishedContent\PublishedMediaTests.cs" />
|
||||
<Compile Include="HashCodeCombinerTests.cs" />
|
||||
<Compile Include="HtmlHelperExtensionMethodsTests.cs" />
|
||||
<Compile Include="Mvc\HtmlHelperExtensionMethodsTests.cs" />
|
||||
<Compile Include="IO\IOHelperTest.cs" />
|
||||
<Compile Include="LibraryTests.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditorValueConverterTests.cs" />
|
||||
@@ -462,15 +464,15 @@
|
||||
<DependentUpon>ImportResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Services\ThreadSafetyServiceTest.cs" />
|
||||
<Compile Include="Surface\PluginControllerAreaTests.cs" />
|
||||
<Compile Include="Sync\DistributedCacheTests.cs" />
|
||||
<Compile Include="Controllers\PluginControllerAreaTests.cs" />
|
||||
<Compile Include="DistributedCache\DistributedCacheTests.cs" />
|
||||
<Compile Include="Templates\MasterPageHelperTests.cs" />
|
||||
<Compile Include="TestHelpers\BaseDatabaseFactoryTest.cs" />
|
||||
<Compile Include="TestHelpers\BaseRoutingTest.cs" />
|
||||
<Compile Include="TestHelpers\BaseUmbracoApplicationTest.cs" />
|
||||
<Compile Include="TestHelpers\DatabaseBehavior.cs" />
|
||||
<Compile Include="TestHelpers\SettingsForTests.cs" />
|
||||
<Compile Include="GlobalSettingsTests.cs" />
|
||||
<Compile Include="Configurations\GlobalSettingsTests.cs" />
|
||||
<Compile Include="Routing\ContentFinderByAliasTests.cs" />
|
||||
<Compile Include="Routing\ContentFinderByIdTests.cs" />
|
||||
<Compile Include="Routing\ContentFinderByNiceUrlAndTemplateTests.cs" />
|
||||
@@ -488,11 +490,11 @@
|
||||
<Compile Include="TestHelpers\Entities\MockedEntity.cs" />
|
||||
<Compile Include="TestHelpers\Entities\MockedMedia.cs" />
|
||||
<Compile Include="TestHelpers\DisposableUmbracoTest.cs" />
|
||||
<Compile Include="Trees\BaseContentTreeTests.cs" />
|
||||
<Compile Include="Trees\BaseMediaTreeTests.cs" />
|
||||
<Compile Include="TreesAndSections\BaseContentTreeTests.cs" />
|
||||
<Compile Include="TreesAndSections\BaseMediaTreeTests.cs" />
|
||||
<Compile Include="UmbracoExamine\ContentServiceTest.cs" />
|
||||
<Compile Include="UmbracoExamine\EventsTest.cs" />
|
||||
<Compile Include="TypeHelperTests.cs" />
|
||||
<Compile Include="Plugins\TypeHelperTests.cs" />
|
||||
<Compile Include="UmbracoExamine\ExamineBaseTest.cs" />
|
||||
<Compile Include="UmbracoExamine\IndexInitializer.cs" />
|
||||
<Compile Include="UmbracoExamine\IndexTest.cs" />
|
||||
@@ -512,11 +514,11 @@
|
||||
<Compile Include="UriExtensionsTests.cs" />
|
||||
<Compile Include="UriUtilityTests.cs" />
|
||||
<Compile Include="Resolvers\MacroFieldEditorsResolverTests.cs" />
|
||||
<Compile Include="MacroEngineFactoryTests.cs" />
|
||||
<Compile Include="Macros\MacroEngineFactoryTests.cs" />
|
||||
<Compile Include="MediaFactoryTests.cs" />
|
||||
<Compile Include="Resolvers\PackageActionsResolverTests.cs" />
|
||||
<Compile Include="PluginManagerExtensions.cs" />
|
||||
<Compile Include="PluginManagerTests.cs" />
|
||||
<Compile Include="Plugins\PluginManagerExtensions.cs" />
|
||||
<Compile Include="Plugins\PluginManagerTests.cs" />
|
||||
<Compile Include="TestHelpers\Stubs\FakeLastChanceFinder.cs" />
|
||||
<Compile Include="TestHelpers\TestHelper.cs" />
|
||||
<Compile Include="EnumerableExtensionsTests.cs" />
|
||||
@@ -526,7 +528,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="CoreStrings\StringExtensionsTests.cs" />
|
||||
<Compile Include="TestHelpers\FakeHttpContextFactory.cs" />
|
||||
<Compile Include="TypeFinderTests.cs" />
|
||||
<Compile Include="Plugins\TypeFinderTests.cs" />
|
||||
<Compile Include="Routing\UmbracoModuleTests.cs" />
|
||||
<Compile Include="XmlExtensionsTests.cs" />
|
||||
<Compile Include="XmlHelperTests.cs" />
|
||||
@@ -696,9 +698,7 @@
|
||||
<Content Include="Services\Importing\uBlogsy-Package.xml" />
|
||||
<Content Include="Services\Importing\XsltSearch-Package.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Install\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
//used for the media picker dialog
|
||||
|
||||
//TODO: SD: Pretty sure we don't want this anymore and we should just be using the treepicker.html instead for all tree picking.
|
||||
|
||||
//used for the content picker dialog
|
||||
angular.module("umbraco").controller("Umbraco.Dialogs.ContentPickerController",
|
||||
function ($scope, eventsService, entityResource, searchService, $log) {
|
||||
var dialogOptions = $scope.dialogOptions;
|
||||
|
||||
@@ -86,8 +86,14 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific
|
||||
$scope.pagination[i] = { index: i, name: i + 1 };
|
||||
}
|
||||
|
||||
//NOTE: This might occur if we are requesting a higher page number than what is actually available, for example
|
||||
// if you have more than one page and you delete all items on the last page. In this case, we need to reset to the last
|
||||
// available page and then re-load again
|
||||
if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) {
|
||||
$scope.options.pageNumber = $scope.listViewResultSet.totalPages;
|
||||
|
||||
//reload!
|
||||
$scope.reloadView(id);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<div class="umb-editor umb-multiple-textbox" ng-controller="Umbraco.PropertyEditors.MultipleTextBoxController">
|
||||
|
||||
<div class="control-group" ng-repeat="item in model.value">
|
||||
<input type="text" name="item_{{$index}}" ng-model="item.value" />
|
||||
<input type="text" name="item_{{$index}}" ng-model="item.value" class="umb-editor" />
|
||||
<a prevent-default href="" title="Remove this text box"
|
||||
ng-show="model.value.length > model.config.min"
|
||||
ng-click="remove($index)">
|
||||
|
||||
@@ -132,9 +132,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\ImageProcessor.1.9.5.0\lib\ImageProcessor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ImageProcessor.Web, Version=3.2.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="ImageProcessor.Web, Version=3.3.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\ImageProcessor.Web.3.3.0.0\lib\net45\ImageProcessor.Web.dll</HintPath>
|
||||
<HintPath>..\packages\ImageProcessor.Web.3.3.1.0\lib\net45\ImageProcessor.Web.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@@ -199,6 +199,7 @@
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -223,9 +224,11 @@
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.30506.0\lib\net40\System.Web.Http.WebHost.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
@@ -2512,8 +2515,10 @@
|
||||
<Folder Include="Views\Partials\" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0</VSToolsPath>
|
||||
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0</VSToolsPath>
|
||||
<VSToolsPath Condition="exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0')">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
@@ -2530,9 +2535,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7150</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7190</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7150</IISUrl>
|
||||
<IISUrl>http://localhost:7190</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<log4net>
|
||||
|
||||
<root>
|
||||
<priority value="Info"/>
|
||||
<appender-ref ref="AsynchronousLog4NetAppender" />
|
||||
</root>
|
||||
|
||||
|
||||
<!--To Change the way logging works for certain namespaces, insert a new logger like: -->
|
||||
<!--
|
||||
<logger name="Umbraco.Core">
|
||||
<level value="WARN" />
|
||||
</logger>-->
|
||||
|
||||
|
||||
<appender name="AsynchronousLog4NetAppender" type="Umbraco.Core.Logging.AsynchronousRollingFileAppender, Umbraco.Core">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
@@ -23,4 +17,12 @@
|
||||
</layout>
|
||||
<encoding value="utf-8" />
|
||||
</appender>
|
||||
|
||||
<!--Here you can change the way logging works for certain namespaces -->
|
||||
|
||||
<logger name="NHibernate">
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
|
||||
|
||||
</log4net>
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<log4net>
|
||||
|
||||
<root>
|
||||
<priority value="Debug"/>
|
||||
<appender-ref ref="AsynchronousLog4NetAppender" />
|
||||
</root>
|
||||
|
||||
|
||||
<!--To Change the way logging works for certain namespaces, insert a new logger like: -->
|
||||
<!--
|
||||
<logger name="Umbraco.Core">
|
||||
<level value="WARN" />
|
||||
</logger>-->
|
||||
|
||||
|
||||
<appender name="AsynchronousLog4NetAppender" type="Umbraco.Core.Logging.AsynchronousRollingFileAppender, Umbraco.Core">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
@@ -23,4 +18,12 @@
|
||||
</layout>
|
||||
<encoding value="utf-8" />
|
||||
</appender>
|
||||
|
||||
<!--Here you can change the way logging works for certain namespaces -->
|
||||
|
||||
<logger name="NHibernate">
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
|
||||
|
||||
</log4net>
|
||||
@@ -5,7 +5,7 @@
|
||||
<package id="ClientDependency-Mvc" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.57.2941" targetFramework="net40" />
|
||||
<package id="ImageProcessor" version="1.9.5.0" targetFramework="net45" />
|
||||
<package id="ImageProcessor.Web" version="3.3.0.0" targetFramework="net45" />
|
||||
<package id="ImageProcessor.Web" version="3.3.1.0" targetFramework="net45" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="da" intName="Danish" localName="dansk" lcid="6" culture="da-DK">
|
||||
<creator>
|
||||
<name>The umbraco community</name>
|
||||
<link>http://umbraco.org/documentation/language-files</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Tilføj domæne</key>
|
||||
@@ -368,7 +368,7 @@
|
||||
<key alias="databaseInstall"><![CDATA[Tryk på <strong>installér</strong> knappen for at installere Umbraco %0% databasen]]></key>
|
||||
<key alias="databaseInstallDone"><![CDATA[Umbraco %0% er nu blevet kopieret til din database. Tryk på <string>Næste</strong> for at fortsætte.]]></key>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>Databasen er ikke fundet. Kontrollér venligst at informationen i database forbindelsesstrengen i "web.config" filen er korrekt.</p>
|
||||
<p>For at fortsætte bedes du venligst rette "web.config" filen (ved at bruge Visual Studio eller dit favoritprogram), scroll til bunden, tilføj forbindelsesstrengen til din database i feltet som hedder "umbracoDbDSN" og gem filen.</p><p>Klik på <strong>Forsøg igen</strong> knappen når du er færdig.<br/><a href="http://umbraco.org/redir/installWebConfig" target="_blank">Mere information om at redigere web.config her.</a></p>]]></key>
|
||||
<p>For at fortsætte bedes du venligst rette "web.config" filen (ved at bruge Visual Studio eller dit favoritprogram), scroll til bunden, tilføj forbindelsesstrengen til din database i feltet som hedder "umbracoDbDSN" og gem filen.</p><p>Klik på <strong>Forsøg igen</strong> knappen når du er færdig.<br/><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">Mere information om at redigere web.config her.</a></p>]]></key>
|
||||
<key alias="databaseText"><![CDATA[For at afslutte dette skridt er du nødt til at have nogle informationer om din database parat ("database forbindelsesstrengen").<br/>Kontakt venligst din ISP hvis det er nødvendigt. Hvis du installerer på en lokal maskine eller server kan du muligvis få informationerne fra din systemadministrator.]]></key>
|
||||
<key alias="databaseUpgrade"><![CDATA[<p>Tryk på <strong>Opgradér</strong> knappen for at opgradere din database til Umbraco %0%</p><p>Bare rolig - intet indhold vil blive slettet og alt vil stadig fungere bagefter!</p>]]></key>
|
||||
<key alias="databaseUpgradeDone"><![CDATA[Din database er blevet opgraderet til den endelige version %0%.<br/>Tryk på <strong>Næste</strong> for at fortsætte.]]></key>
|
||||
@@ -446,7 +446,7 @@
|
||||
<key alias="timeout">Din session er udløbet</key>
|
||||
|
||||
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p> ]]></key>
|
||||
</area>
|
||||
<area alias="main">
|
||||
<key alias="dashboard">Skrivebord</key>
|
||||
@@ -481,7 +481,11 @@ Ha' en dejlig dag!
|
||||
|
||||
Mange hilsner fra umbraco robotten
|
||||
]]></key>
|
||||
<key alias="mailBodyHtml"><![CDATA[<p>Hej %0%</p> <p>Dette er en automatisk mail for at informere dig om at opgaven <strong>'%1%'</strong> er blevet udførtpå siden <a href="http://%4%/#/content/content/edit/%5%"><strong>'%2%'</strong></a> af brugeren <strong>'%3%'</strong> </p> <div style="margin: 8px 0; padding: 8px; display: block;"> <br /> <a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%"> RET </a> <br /> </div> <p> <h3>Opdateringssammendrag:</h3> <table style="width: 100%;"> %6% </table> </p> <div style="margin: 8px 0; padding: 8px; display: block;"> <br /> <a style="color: white; font-weight: bold; background-color: #66cc66; text-decoration : none; margin-right: 20px; border: 8px solid #66cc66; width: 150px;" href="http://%4%/actions/publish.aspx?id=%5%"> PUBLISÉR </a> <a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%"> RET </a> <a style="color: white; font-weight: bold; background-color: #ca4a4a; text-decoration : none; margin-right: 20px; border: 8px solid #ca4a4a; width: 150px;" href="http://%4%/actions/delete.aspx?id=%5%"> SLET </a> <br /> </div> <p>Hav en fortsat god dag!<br /><br /> De bedste hilsner fra umbraco robotten </p>]]></key>
|
||||
<key alias="mailBodyHtml"><![CDATA[<p>Hej %0%</p>
|
||||
<p>Dette er en automatisk mail for at informere dig om at opgaven <strong>'%1%'</strong>
|
||||
er blevet udførtpå siden <a href="http://%4%/#/content/content/edit/%5%"><strong>'%2%'</strong></a> af brugeren <strong>'%3%'</strong> </p>
|
||||
<div style="margin: 8px 0; padding: 8px; display: block;"> <br />
|
||||
<a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%"> RET </a> <br /> </div> <p> <h3>Opdateringssammendrag:</h3> <table style="width: 100%;"> %6% </table> </p> <div style="margin: 8px 0; padding: 8px; display: block;"> <br /> <a style="color: white; font-weight: bold; background-color: #66cc66; text-decoration : none; margin-right: 20px; border: 8px solid #66cc66; width: 150px;" href="http://%4%/actions/publish.aspx?id=%5%"> PUBLISÉR </a> <a style="color: white; font-weight: bold; background-color: #5372c3; text-decoration : none; margin-right: 20px; border: 8px solid #5372c3; width: 150px;" href="http://%4%/#/content/content/edit/%5%"> RET </a> <a style="color: white; font-weight: bold; background-color: #ca4a4a; text-decoration : none; margin-right: 20px; border: 8px solid #ca4a4a; width: 150px;" href="http://%4%/actions/delete.aspx?id=%5%"> SLET </a> <br /> </div> <p>Hav en fortsat god dag!<br /><br /> De bedste hilsner fra umbraco robotten </p>]]></key>
|
||||
<key alias="mailSubject">[%0%] Notificering om %1% udført på %2%</key>
|
||||
<key alias="notifications">Notificeringer</key>
|
||||
</area>
|
||||
@@ -542,7 +546,7 @@ Mange hilsner fra umbraco robotten
|
||||
<key alias="inProgressCounter">%0% ud af %1% sider er blevet udgivet...</key>
|
||||
<key alias="nodePublish">%0% er nu publiceret</key>
|
||||
<key alias="nodePublishAll">%0% og alle undersider er nu publiceret</key>
|
||||
<key alias="publishAll">Publisér alle undersider</key>
|
||||
<key alias="publishAll">Publicér alle undersider</key>
|
||||
<key alias="publishHelp"><![CDATA[Klik <em>ok</em> for at udgive <strong>%0%</strong> og derved gøre indholdet offentligt tilgængeligt..<br/><br /> Du kan udgive denne side og dens undersider ved at klikke <em>Udgiv alle undersider</em> forneden]]></key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
@@ -596,6 +600,8 @@ Mange hilsner fra umbraco robotten
|
||||
<key alias="tab">Faneblad</key>
|
||||
<key alias="tabname">Titel på faneblad</key>
|
||||
<key alias="tabs">Faneblade</key>
|
||||
<key alias="masterDocumentType">Master Dokument Type</key>
|
||||
<key alias="createMatchingTemplate">Opret matchende skabelon</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortDone">Sortering udført</key>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<language alias="de" intName="German" localName="Deutsch" lcid="7" culture="de-DE">
|
||||
<creator>
|
||||
<name>The German Umbraco Community</name>
|
||||
<link>http://umbraco.org</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Hostnamen verwalten</key>
|
||||
@@ -465,7 +465,7 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die
|
||||
<key alias="renewSession">Erneuern Sie, um Ihre Arbeit zu speichern ...</key>
|
||||
</area>
|
||||
<area alias="login">
|
||||
<key alias="bottomText"><p style="text-align:right;">&copy; 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> </key>
|
||||
<key alias="bottomText"><p style="text-align:right;">&copy; 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.org</a></p> </key>
|
||||
<key alias="greeting1">Einen wunderbaren Sonntag</key>
|
||||
<key alias="greeting6">Frohen freundlichen Freitag</key>
|
||||
<key alias="greeting5">Donnerwetter Donnerstag</key>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="en" intName="English (UK)" localName="English (UK)" lcid="" culture="en-GB">
|
||||
<creator>
|
||||
<name>umbraco</name>
|
||||
<link>http://umbraco.org</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Culture and Hostnames</key>
|
||||
@@ -44,16 +44,16 @@
|
||||
<key alias="invalidNode">Invalid node.</key>
|
||||
<key alias="invalidDomain">Invalid domain format.</key>
|
||||
<key alias="duplicateDomain">Domain has already been assigned.</key>
|
||||
<key alias="domain">Domain</key>
|
||||
<key alias="language">Language</key>
|
||||
<key alias="domain">Domain</key>
|
||||
<key alias="domainCreated">New domain '%0%' has been created</key>
|
||||
<key alias="domainDeleted">Domain '%0%' is deleted</key>
|
||||
<key alias="domainExists">Domain '%0%' has already been assigned</key>
|
||||
<key alias="domainUpdated">Domain '%0%' has been updated</key>
|
||||
<key alias="orEdit">Edit Current Domains</key>
|
||||
<key alias="domainHelp"><![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
should be avoided. Better use the culture setting above.]]></key>
|
||||
<key alias="domainUpdated">Domain '%0%' has been updated</key>
|
||||
<key alias="orEdit">Edit Current Domains</key>
|
||||
<key alias="inherit">Inherit</key>
|
||||
<key alias="setLanguage">Culture</key>
|
||||
<key alias="setLanguageHelp"><![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
|
||||
@@ -130,7 +130,7 @@
|
||||
<key alias="itemChanged">This item has been changed after publication</key>
|
||||
<key alias="itemNotPublished">This item is not published</key>
|
||||
<key alias="lastPublished">Last published</key>
|
||||
<key alias="listViewNoItems" version="7.1.5">There are no items show in the list.</key>
|
||||
<key alias="listViewNoItems" version="7.1.5">There are no items to show in the list.</key>
|
||||
<key alias="mediatype">Media Type</key>
|
||||
<key alias="mediaLinks">Link to media item(s)</key>
|
||||
<key alias="membergroup">Member Group</key>
|
||||
@@ -418,11 +418,11 @@
|
||||
Press the <strong>install</strong> button to install the Umbraco %0% database
|
||||
]]></key>
|
||||
<key alias="databaseInstallDone"><![CDATA[Umbraco %0% has now been copied to your database. Press <strong>Next</strong> to proceed.]]></key>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>Database not found! Please check that the information in the "connection string" of the “web.config” file is correct.</p>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.</p>
|
||||
<p>To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "umbracoDbDSN" and save the file. </p>
|
||||
<p>
|
||||
Click the <strong>retry</strong> button when
|
||||
done.<br /><a href="http://umbraco.org/redir/installWebConfig" target="_blank">
|
||||
done.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">
|
||||
More information on editing web.config here.</a></p>]]></key>
|
||||
<key alias="databaseText"><![CDATA[To complete this step, you must know some information regarding your database server ("connection string").<br />
|
||||
Please contact your ISP if necessary.
|
||||
@@ -437,7 +437,7 @@
|
||||
<key alias="databaseUpgradeDone"><![CDATA[Your database has been upgraded to the final version %0%.<br />Press <strong>Next</strong> to
|
||||
proceed. ]]></key>
|
||||
<key alias="databaseUpToDate"><![CDATA[Your current database is up-to-date!. Click <strong>next</strong> to continue the configuration wizard]]></key>
|
||||
<key alias="defaultUserChangePass"><![CDATA[<strong>The Default users’ password needs to be changed!</strong>]]></key>
|
||||
<key alias="defaultUserChangePass"><![CDATA[<strong>The Default users' password needs to be changed!</strong>]]></key>
|
||||
<key alias="defaultUserDisabled"><![CDATA[<strong>The Default user has been disabled or has no access to Umbraco!</strong></p><p>No further actions needs to be taken. Click <b>Next</b> to proceed.]]></key>
|
||||
<key alias="defaultUserPassChanged"><![CDATA[<strong>The Default user's password has been successfully changed since the installation!</strong></p><p>No further actions needs to be taken. Click <strong>Next</strong> to proceed.]]></key>
|
||||
<key alias="defaultUserPasswordChanged">The password is changed!</key>
|
||||
@@ -478,11 +478,11 @@
|
||||
]]></key>
|
||||
<key alias="runwayFromScratch">I want to start from scratch</key>
|
||||
<key alias="runwayFromScratchText"><![CDATA[
|
||||
Your website is completely empty at the moment, so that’s perfect if you want to start from scratch and create your own document types and templates.
|
||||
Your website is completely empty at the moment, so that's perfect if you want to start from scratch and create your own document types and templates.
|
||||
(<a href="http://umbraco.tv/documentation/videos/for-site-builders/foundation/document-types">learn how</a>)
|
||||
You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
|
||||
]]></key>
|
||||
<key alias="runwayHeader">You’ve just set up a clean Umbraco platform. What do you want to do next?</key>
|
||||
<key alias="runwayHeader">You've just set up a clean Umbraco platform. What do you want to do next?</key>
|
||||
<key alias="runwayInstalled">Runway is installed</key>
|
||||
<key alias="runwayInstalledText"><![CDATA[
|
||||
You have the foundation in place. Select what modules you wish to install on top of it.<br />
|
||||
@@ -493,7 +493,7 @@
|
||||
<key alias="runwaySimpleSiteText"><![CDATA[
|
||||
<p>
|
||||
"Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
|
||||
but you can easily edit, extend or remove it. It’s not necessary and you can perfectly use Umbraco without it. However,
|
||||
but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However,
|
||||
Runway offers an easy foundation based on best practices to get you started faster than ever.
|
||||
If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages.
|
||||
</p>
|
||||
@@ -751,6 +751,8 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="contentTypeUses">This Content Type uses</key>
|
||||
<key alias="asAContentMasterType">as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself</key>
|
||||
<key alias="noPropertiesDefinedOnTab">No properties defined on this tab. Click on the "add a new property" link at the top to create a new property.</key>
|
||||
<key alias="masterDocumentType">Master Document Type</key>
|
||||
<key alias="createMatchingTemplate">Create matching template</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortDone">Sorting complete.</key>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="en_us" intName="English (US)" localName="English (US)" lcid="" culture="en-US">
|
||||
<creator>
|
||||
<name>umbraco</name>
|
||||
<link>http://umbraco.org</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Culture and Hostnames</key>
|
||||
@@ -133,6 +133,7 @@
|
||||
<key alias="itemChanged">This item has been changed after publication</key>
|
||||
<key alias="itemNotPublished">This item is not published</key>
|
||||
<key alias="lastPublished">Last published</key>
|
||||
<key alias="listViewNoItems" version="7.1.5">There are no items show in the list.</key>
|
||||
<key alias="mediatype">Media Type</key>
|
||||
<key alias="mediaLinks">Link to media item(s)</key>
|
||||
<key alias="membergroup">Member Group</key>
|
||||
@@ -152,6 +153,7 @@
|
||||
<key alias="sortHelp">To sort the nodes, simply drag the nodes or click one of the column headers. You can select multiple nodes by holding the "shift" or "control" key while selecting</key>
|
||||
<key alias="statistics">Statistics</key>
|
||||
<key alias="titleOptional">Title (optional)</key>
|
||||
<key alias="altTextOptional">Alternative text (optional)</key>
|
||||
<key alias="type">Type</key>
|
||||
<key alias="unPublish">Unpublish</key>
|
||||
<key alias="updateDate">Last edited</key>
|
||||
@@ -180,7 +182,7 @@
|
||||
<area alias="dashboard">
|
||||
<key alias="browser">Browse your website</key>
|
||||
<key alias="dontShowAgain">- Hide</key>
|
||||
<key alias="nothinghappens">If umbraco isn't opening, you might need to allow popups from this site</key>
|
||||
<key alias="nothinghappens">If Umbraco isn't opening, you might need to allow popups from this site</key>
|
||||
<key alias="openinnew">has opened in a new window</key>
|
||||
<key alias="restart">Restart</key>
|
||||
<key alias="visit">Visit</key>
|
||||
@@ -208,7 +210,7 @@
|
||||
<key alias="lastEdited">Last Edited</key>
|
||||
<key alias="link">Link</key>
|
||||
<key alias="linkinternal">Internal link:</key>
|
||||
<key alias="linklocaltip">When using local links, insert "#" infront of link</key>
|
||||
<key alias="linklocaltip">When using local links, insert "#" in front of link</key>
|
||||
<key alias="linknewwindow">Open in new window?</key>
|
||||
<key alias="macroContainerSettings">Macro Settings</key>
|
||||
<key alias="macroDoesNotHaveProperties">This macro does not contain any properties you can edit</key>
|
||||
@@ -222,7 +224,7 @@
|
||||
<key alias="removeMacro">Remove Macro</key>
|
||||
<key alias="requiredField">Required Field</key>
|
||||
<key alias="sitereindexed">Site is reindexed</key>
|
||||
<key alias="siterepublished">The website cache has been refreshed. All publish content is now uptodate. While all unpublished content is still unpublished</key>
|
||||
<key alias="siterepublished">The website cache has been refreshed. All publish content is now up to date. While all unpublished content is still unpublished</key>
|
||||
<key alias="siterepublishHelp">The website cache will be refreshed. All published content will be updated, while unpublished content will stay unpublished.</key>
|
||||
<key alias="tableColumns">Number of columns</key>
|
||||
<key alias="tableRows">Number of rows</key>
|
||||
@@ -250,7 +252,8 @@
|
||||
</area>
|
||||
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowedchildnodetypes">Allowed child nodetypes</key>
|
||||
<key alias="allowedchildnodetypes">Allowed child node types</key>
|
||||
<key alias="contenttypecompositions">Document Type Compositions</key>
|
||||
<key alias="create">Create</key>
|
||||
<key alias="deletetab">Delete tab</key>
|
||||
<key alias="description">Description</key>
|
||||
@@ -274,7 +277,7 @@
|
||||
</area>
|
||||
<area alias="errorHandling">
|
||||
<key alias="errorButDataWasSaved">Your data has been saved, but before you can publish this page there are some errors you need to fix first:</key>
|
||||
<key alias="errorChangingProviderPassword">The current MemberShip Provider does not support changing password (EnablePasswordRetrieval need to be true)</key>
|
||||
<key alias="errorChangingProviderPassword">The current membership provider does not support changing password (EnablePasswordRetrieval need to be true)</key>
|
||||
<key alias="errorExistsWithoutTab">%0% already exists</key>
|
||||
<key alias="errorHeader">There were errors:</key>
|
||||
<key alias="errorHeaderWithoutTab">There were errors:</key>
|
||||
@@ -288,7 +291,7 @@
|
||||
<area alias="errors">
|
||||
<key alias="dissallowedMediaType">The specified file type has been disallowed by the administrator</key>
|
||||
<key alias="codemirroriewarning">NOTE! Even though CodeMirror is enabled by configuration, it is disabled in Internet Explorer because it's not stable enough.</key>
|
||||
<key alias="contentTypeAliasAndNameNotNull">Please fill both alias and name on the new propertytype!</key>
|
||||
<key alias="contentTypeAliasAndNameNotNull">Please fill both alias and name on the new property type!</key>
|
||||
<key alias="filePermissionsError">There is a problem with read/write access to a specific file or folder</key>
|
||||
<key alias="missingTitle">Please enter a title</key>
|
||||
<key alias="missingType">Please choose a type</key>
|
||||
@@ -423,11 +426,11 @@
|
||||
Press the <strong>install</strong> button to install the Umbraco %0% database
|
||||
]]></key>
|
||||
<key alias="databaseInstallDone"><![CDATA[Umbraco %0% has now been copied to your database. Press <strong>Next</strong> to proceed.]]></key>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>Database not found! Please check that the information in the "connection string" of the “web.config” file is correct.</p>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.</p>
|
||||
<p>To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "umbracoDbDSN" and save the file. </p>
|
||||
<p>
|
||||
Click the <strong>retry</strong> button when
|
||||
done.<br /><a href="http://umbraco.org/redir/installWebConfig" target="_blank">
|
||||
done.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">
|
||||
More information on editing web.config here.</a></p>]]></key>
|
||||
<key alias="databaseText"><![CDATA[To complete this step, you must know some information regarding your database server ("connection string").<br />
|
||||
Please contact your ISP if necessary.
|
||||
@@ -442,13 +445,13 @@
|
||||
<key alias="databaseUpgradeDone"><![CDATA[Your database has been upgraded to the final version %0%.<br />Press <strong>Next</strong> to
|
||||
proceed. ]]></key>
|
||||
<key alias="databaseUpToDate"><![CDATA[Your current database is up-to-date!. Click <strong>next</strong> to continue the configuration wizard]]></key>
|
||||
<key alias="defaultUserChangePass"><![CDATA[<strong>The Default users’ password needs to be changed!</strong>]]></key>
|
||||
<key alias="defaultUserDisabled"><![CDATA[<strong>The Default user has been disabled or has no access to umbraco!</strong></p><p>No further actions needs to be taken. Click <b>Next</b> to proceed.]]></key>
|
||||
<key alias="defaultUserChangePass"><![CDATA[<strong>The Default users' password needs to be changed!</strong>]]></key>
|
||||
<key alias="defaultUserDisabled"><![CDATA[<strong>The Default user has been disabled or has no access to Umbraco!</strong></p><p>No further actions needs to be taken. Click <b>Next</b> to proceed.]]></key>
|
||||
<key alias="defaultUserPassChanged"><![CDATA[<strong>The Default user's password has been successfully changed since the installation!</strong></p><p>No further actions needs to be taken. Click <strong>Next</strong> to proceed.]]></key>
|
||||
<key alias="defaultUserPasswordChanged">The password is changed!</key>
|
||||
<key alias="defaultUserText"><![CDATA[
|
||||
<p>
|
||||
umbraco creates a default user with a login <strong>('admin')</strong> and password <strong>('default')</strong>. It's <strong>important</strong> that the password is
|
||||
Umbraco creates a default user with a login <strong>('admin')</strong> and password <strong>('default')</strong>. It's <strong>important</strong> that the password is
|
||||
changed to something unique.
|
||||
</p>
|
||||
<p>
|
||||
@@ -456,38 +459,38 @@
|
||||
</p>
|
||||
]]></key>
|
||||
<key alias="greatStart">Get a great start, watch our introduction videos</key>
|
||||
<key alias="licenseText">By clicking the next button (or modifying the umbracoConfigurationStatus in web.config), you accept the license for this software as specified in the box below. Notice that this umbraco distribution consists of two different licenses, the open source MIT license for the framework and the umbraco freeware license that covers the UI.</key>
|
||||
<key alias="licenseText">By clicking the next button (or modifying the umbracoConfigurationStatus in web.config), you accept the license for this software as specified in the box below. Notice that this Umbraco distribution consists of two different licenses, the open source MIT license for the framework and the Umbraco freeware license that covers the UI.</key>
|
||||
<key alias="None">Not installed yet.</key>
|
||||
<key alias="permissionsAffectedFolders">Affected files and folders</key>
|
||||
<key alias="permissionsAffectedFoldersMoreInfo">More information on setting up permissions for umbraco here</key>
|
||||
<key alias="permissionsAffectedFoldersMoreInfo">More information on setting up permissions for Umbraco here</key>
|
||||
<key alias="permissionsAffectedFoldersText">You need to grant ASP.NET modify permissions to the following files/folders</key>
|
||||
<key alias="permissionsAlmostPerfect"><![CDATA[<strong>Your permission settings are almost perfect!</strong><br /><br />
|
||||
You can run umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of umbraco.]]></key>
|
||||
You can run Umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of Umbraco.]]></key>
|
||||
<key alias="permissionsHowtoResolve">How to Resolve</key>
|
||||
<key alias="permissionsHowtoResolveLink">Click here to read the text version</key>
|
||||
<key alias="permissionsHowtoResolveText"><![CDATA[Watch our <strong>video tutorial</strong> on setting up folder permissions for umbraco or read the text version.]]></key>
|
||||
<key alias="permissionsHowtoResolveText"><![CDATA[Watch our <strong>video tutorial</strong> on setting up folder permissions for Umbraco or read the text version.]]></key>
|
||||
<key alias="permissionsMaybeAnIssue"><![CDATA[<strong>Your permission settings might be an issue!</strong>
|
||||
<br/><br />
|
||||
You can run umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of umbraco.]]></key>
|
||||
<key alias="permissionsNotReady"><![CDATA[<strong>Your permission settings are not ready for umbraco!</strong>
|
||||
You can run Umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of Umbraco.]]></key>
|
||||
<key alias="permissionsNotReady"><![CDATA[<strong>Your permission settings are not ready for Umbraco!</strong>
|
||||
<br /><br />
|
||||
In order to run umbraco, you'll need to update your permission settings.]]></key>
|
||||
In order to run Umbraco, you'll need to update your permission settings.]]></key>
|
||||
<key alias="permissionsPerfect"><![CDATA[<strong>Your permission settings are perfect!</strong><br /><br />
|
||||
You are ready to run umbraco and install packages!]]></key>
|
||||
You are ready to run Umbraco and install packages!]]></key>
|
||||
<key alias="permissionsResolveFolderIssues">Resolving folder issue</key>
|
||||
<key alias="permissionsResolveFolderIssuesLink">Follow this link for more information on problems with ASP.NET and creating folders</key>
|
||||
<key alias="permissionsSettingUpPermissions">Setting up folder permissions</key>
|
||||
<key alias="permissionsText"><![CDATA[
|
||||
umbraco needs write/modify access to certain directories in order to store files like pictures and PDF's.
|
||||
Umbraco needs write/modify access to certain directories in order to store files like pictures and PDF's.
|
||||
It also stores temporary data (aka: cache) for enhancing the performance of your website.
|
||||
]]></key>
|
||||
<key alias="runwayFromScratch">I want to start from scratch</key>
|
||||
<key alias="runwayFromScratchText"><![CDATA[
|
||||
Your website is completely empty at the moment, so that’s perfect if you want to start from scratch and create your own document types and templates.
|
||||
Your website is completely empty at the moment, so that's perfect if you want to start from scratch and create your own document types and templates.
|
||||
(<a href="http://umbraco.tv/documentation/videos/for-site-builders/foundation/document-types">learn how</a>)
|
||||
You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
|
||||
]]></key>
|
||||
<key alias="runwayHeader">You’ve just set up a clean Umbraco platform. What do you want to do next?</key>
|
||||
<key alias="runwayHeader">You've just set up a clean Umbraco platform. What do you want to do next?</key>
|
||||
<key alias="runwayInstalled">Runway is installed</key>
|
||||
<key alias="runwayInstalledText"><![CDATA[
|
||||
You have the foundation in place. Select what modules you wish to install on top of it.<br />
|
||||
@@ -498,7 +501,7 @@
|
||||
<key alias="runwaySimpleSiteText"><![CDATA[
|
||||
<p>
|
||||
"Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
|
||||
but you can easily edit, extend or remove it. It’s not necessary and you can perfectly use Umbraco without it. However,
|
||||
but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However,
|
||||
Runway offers an easy foundation based on best practices to get you started faster than ever.
|
||||
If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages.
|
||||
</p>
|
||||
@@ -511,25 +514,25 @@
|
||||
<key alias="step1">Step 1/5 Accept license</key>
|
||||
<key alias="step2">Step 2/5: Database configuration</key>
|
||||
<key alias="step3">Step 3/5: Validating File Permissions</key>
|
||||
<key alias="step4">Step 4/5: Check umbraco security</key>
|
||||
<key alias="step4">Step 4/5: Check Umbraco security</key>
|
||||
<key alias="step5">Step 5/5: Umbraco is ready to get you started</key>
|
||||
<key alias="thankYou">Thank you for choosing umbraco</key>
|
||||
<key alias="thankYou">Thank you for choosing Umbraco</key>
|
||||
<key alias="theEndBrowseSite"><![CDATA[<h3>Browse your new site</h3>
|
||||
You installed Runway, so why not see how your new website looks.]]></key>
|
||||
<key alias="theEndFurtherHelp"><![CDATA[<h3>Further help and information</h3>
|
||||
Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the umbraco terminology]]></key>
|
||||
Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the Umbraco terminology]]></key>
|
||||
<key alias="theEndHeader">Umbraco %0% is installed and ready for use</key>
|
||||
<key alias="theEndInstallFailed"><![CDATA[To finish the installation, you'll need to
|
||||
manually edit the <strong>/web.config file</strong> and update the AppSetting key <strong>umbracoConfigurationStatus</strong> in the bottom to the value of <strong>'%0%'</strong>.]]></key>
|
||||
<key alias="theEndInstallSuccess"><![CDATA[You can get <strong>started instantly</strong> by clicking the "Launch Umbraco" button below. <br />If you are <strong>new to umbraco</strong>,
|
||||
<key alias="theEndInstallSuccess"><![CDATA[You can get <strong>started instantly</strong> by clicking the "Launch Umbraco" button below. <br />If you are <strong>new to Umbraco</strong>,
|
||||
you can find plenty of resources on our getting started pages.]]></key>
|
||||
<key alias="theEndOpenUmbraco"><![CDATA[<h3>Launch Umbraco</h3>
|
||||
To manage your website, simply open the umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]></key>
|
||||
To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]></key>
|
||||
<key alias="Unavailable">Connection to database failed.</key>
|
||||
<key alias="Version3">Umbraco Version 3</key>
|
||||
<key alias="Version4">Umbraco Version 4</key>
|
||||
<key alias="watch">Watch</key>
|
||||
<key alias="welcomeIntro"><![CDATA[This wizard will guide you through the process of configuring <strong>umbraco %0%</strong> for a fresh install or upgrading from version 3.0.
|
||||
<key alias="welcomeIntro"><![CDATA[This wizard will guide you through the process of configuring <strong>Umbraco %0%</strong> for a fresh install or upgrading from version 3.0.
|
||||
<br /><br />
|
||||
Press <strong>"next"</strong> to start the wizard.]]></key>
|
||||
</area>
|
||||
@@ -552,8 +555,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
|
||||
<key alias="instruction">log in below</key>
|
||||
<key alias="timeout">Session timed out</key>
|
||||
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">Umbraco.com</a></p> ]]></key>
|
||||
|
||||
</area>
|
||||
<area alias="main">
|
||||
@@ -588,7 +590,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
|
||||
Have a nice day!
|
||||
|
||||
Cheers from the umbraco robot
|
||||
Cheers from the Umbraco robot
|
||||
]]></key>
|
||||
<key alias="mailBodyHtml"><![CDATA[<p>Hi %0%</p>
|
||||
|
||||
@@ -615,7 +617,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
</div>
|
||||
|
||||
<p>Have a nice day!<br /><br />
|
||||
Cheers from the umbraco robot
|
||||
Cheers from the Umbraco robot
|
||||
</p>]]></key>
|
||||
<key alias="mailSubject">[%0%] Notification about %1% performed on %2%</key>
|
||||
<key alias="notifications">Notifications</key>
|
||||
@@ -623,7 +625,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<area alias="packager">
|
||||
<key alias="chooseLocalPackageText"><![CDATA[
|
||||
Choose Package from your machine, by clicking the Browse<br />
|
||||
button and locating the package. umbraco packages usually have a ".umb" or ".zip" extension.
|
||||
button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
|
||||
]]></key>
|
||||
<key alias="packageAuthor">Author</key>
|
||||
<key alias="packageDemonstration">Demonstration</key>
|
||||
@@ -647,20 +649,20 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="packageUpgradeDownload">Download update from the repository</key>
|
||||
<key alias="packageUpgradeHeader">Upgrade package</key>
|
||||
<key alias="packageUpgradeInstructions">Upgrade instructions</key>
|
||||
<key alias="packageUpgradeText"> There's an upgrade available for this package. You can download it directly from the umbraco package repository.</key>
|
||||
<key alias="packageUpgradeText"> There's an upgrade available for this package. You can download it directly from the Umbraco package repository.</key>
|
||||
<key alias="packageVersion">Package version</key>
|
||||
<key alias="packageVersionHistory">Package version history</key>
|
||||
<key alias="viewPackageWebsite">View package website</key>
|
||||
</area>
|
||||
<area alias="paste">
|
||||
<key alias="doNothing">Paste with full formatting (Not recommended)</key>
|
||||
<key alias="errorMessage">The text you're trying to paste contains special characters or formatting. This could be caused by copying text from Microsoft Word. umbraco can remove special characters or formatting automatically, so the pasted content will be more suitable for the web.</key>
|
||||
<key alias="errorMessage">The text you're trying to paste contains special characters or formatting. This could be caused by copying text from Microsoft Word. Umbraco can remove special characters or formatting automatically, so the pasted content will be more suitable for the web.</key>
|
||||
<key alias="removeAll">Paste as raw text without any formatting at all</key>
|
||||
<key alias="removeSpecialFormattering">Paste, but remove formatting (Recommended)</key>
|
||||
</area>
|
||||
<area alias="publicAccess">
|
||||
<key alias="paAdvanced">Role based protection</key>
|
||||
<key alias="paAdvancedHelp"><![CDATA[If you wish to control access to the page using role-based authentication,<br /> using umbraco's member groups.]]></key>
|
||||
<key alias="paAdvancedHelp"><![CDATA[If you wish to control access to the page using role-based authentication,<br /> using Umbraco's member groups.]]></key>
|
||||
<key alias="paAdvancedNoGroups"><![CDATA[You need to create a membergroup before you can use <br />role-based authentication.]]></key>
|
||||
<key alias="paErrorPage">Error Page</key>
|
||||
<key alias="paErrorPageHelp">Used when people are logged on, but do not have access</key>
|
||||
@@ -668,7 +670,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="paIsProtected">%0% is now protected</key>
|
||||
<key alias="paIsRemoved">Protection removed from %0%</key>
|
||||
<key alias="paLoginPage">Login Page</key>
|
||||
<key alias="paLoginPageHelp">Choose the page that has the login formular</key>
|
||||
<key alias="paLoginPageHelp">Choose the page that contains the login form</key>
|
||||
<key alias="paRemoveProtection">Remove Protection</key>
|
||||
<key alias="paSelectPages">Select the pages that contain login form and error messages</key>
|
||||
<key alias="paSelectRoles">Pick the roles who have access to this page</key>
|
||||
@@ -686,7 +688,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
%0% could not be published because these properties: %1% did not pass validation rules.
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByEvent"><![CDATA[
|
||||
%0% could not be published, due to a 3rd party extension cancelling the action.
|
||||
%0% could not be published, a 3rd party add-in cancelled the action.
|
||||
]]></key>
|
||||
<key alias="contentPublishedFailedByParent"><![CDATA[
|
||||
%0% can not be published, because a parent page is not published.
|
||||
@@ -698,7 +700,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="nodePublishAll">%0% and subpages have been published</key>
|
||||
<key alias="publishAll">Publish %0% and all its subpages</key>
|
||||
<key alias="publishHelp"><![CDATA[Click <em>ok</em> to publish <strong>%0%</strong> and thereby making its content publicly available.<br/><br />
|
||||
You can publish this page and all its sub-pages by checking <em>publish all children</em> below.
|
||||
You can publish this page and all it's sub-pages by checking <em>publish all children</em> below.
|
||||
]]></key>
|
||||
</area>
|
||||
<area alias="colorpicker">
|
||||
@@ -720,7 +722,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="currentVersion">Current version</key>
|
||||
<key alias="diffHelp"><![CDATA[This shows the differences between the current version and the selected version<br /><del>Red</del> text will not be shown in the selected version. , <ins>green means added</ins>]]></key>
|
||||
<key alias="documentRolledBack">Document has been rolled back</key>
|
||||
<key alias="htmlHelp">This displays the selected version as html, if you wish to see the difference between 2 versions at the same time, use the diff view</key>
|
||||
<key alias="htmlHelp">This displays the selected version as HTML, if you wish to see the difference between 2 versions at the same time, use the diff view</key>
|
||||
<key alias="rollbackTo">Rollback to</key>
|
||||
<key alias="selectVersion">Select version</key>
|
||||
<key alias="view">View</key>
|
||||
@@ -743,13 +745,14 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="users">Users</key>
|
||||
|
||||
<key alias="help" version="7.0">Help</key>
|
||||
<key alias="analytics">Analytics</key>
|
||||
</area>
|
||||
<area alias="settings">
|
||||
<key alias="defaulttemplate">Default template</key>
|
||||
<key alias="dictionary editor egenskab">Dictionary Key</key>
|
||||
<key alias="importDocumentTypeHelp">To import a document type, find the ".udt" file on your computer by clicking the "Browse" button and click "Import" (you'll be asked for confirmation on the next screen)</key>
|
||||
<key alias="newtabname">New Tab Title</key>
|
||||
<key alias="nodetype">Nodetype</key>
|
||||
<key alias="nodetype">Node type</key>
|
||||
<key alias="objecttype">Type</key>
|
||||
<key alias="stylesheet">Stylesheet</key>
|
||||
<key alias="script">Script</key>
|
||||
@@ -761,6 +764,8 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="contentTypeUses">This Content Type uses</key>
|
||||
<key alias="asAContentMasterType">as a Master Content Type. Tabs from Master Content Types are not shown and can only be edited on the Master Content Type itself</key>
|
||||
<key alias="noPropertiesDefinedOnTab">No properties defined on this tab. Click on the "add a new property" link at the top to create a new property.</key>
|
||||
<key alias="masterDocumentType">Master Document Type</key>
|
||||
<key alias="createMatchingTemplate">Create matching template</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortDone">Sorting complete.</key>
|
||||
@@ -836,9 +841,9 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="insertContentAreaPlaceHolder">Insert content area placeholder</key>
|
||||
<key alias="insertDictionaryItem">Insert dictionary item</key>
|
||||
<key alias="insertMacro">Insert Macro</key>
|
||||
<key alias="insertPageField">Insert umbraco page field</key>
|
||||
<key alias="insertPageField">Insert Umbraco page field</key>
|
||||
<key alias="mastertemplate">Master template</key>
|
||||
<key alias="quickGuide">Quick Guide to umbraco template tags</key>
|
||||
<key alias="quickGuide">Quick Guide to Umbraco template tags</key>
|
||||
<key alias="template">Template</key>
|
||||
</area>
|
||||
<area alias="templateEditor">
|
||||
@@ -847,8 +852,8 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="casing">Casing</key>
|
||||
<key alias="encoding">Encoding</key>
|
||||
<key alias="chooseField">Choose field</key>
|
||||
<key alias="convertLineBreaks">Convert Linebreaks</key>
|
||||
<key alias="convertLineBreaksHelp">Replaces linebreaks with html-tag &lt;br&gt;</key>
|
||||
<key alias="convertLineBreaks">Convert line breaks</key>
|
||||
<key alias="convertLineBreaksHelp">Replaces line breaks with html-tag &lt;br&gt;</key>
|
||||
<key alias="customFields">Custom Fields</key>
|
||||
<key alias="dateOnly">Yes, Date only</key>
|
||||
<key alias="formatAsDate">Format as date</key>
|
||||
@@ -879,9 +884,9 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
]]></key>
|
||||
<key alias="closeTask">close task</key>
|
||||
<key alias="details">Translation details</key>
|
||||
<key alias="downloadAllAsXml">Download all translation tasks as xml</key>
|
||||
<key alias="downloadTaskAsXml">Download xml</key>
|
||||
<key alias="DownloadXmlDTD">Download xml DTD</key>
|
||||
<key alias="downloadAllAsXml">Download all translation tasks as XML</key>
|
||||
<key alias="downloadTaskAsXml">Download XML</key>
|
||||
<key alias="DownloadXmlDTD">Download XML DTD</key>
|
||||
<key alias="fields">Fields</key>
|
||||
<key alias="includeSubpages">Include subpages</key>
|
||||
<key alias="mailBody"><![CDATA[
|
||||
@@ -892,12 +897,12 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
|
||||
Go to http://%3%/translation/details.aspx?id=%4% to edit.
|
||||
|
||||
Or log into umbraco to get an overview of your translation tasks
|
||||
Or log into Umbraco to get an overview of your translation tasks
|
||||
http://%3%
|
||||
|
||||
Have a nice day!
|
||||
|
||||
Cheers from the umbraco robot
|
||||
Cheers from the Umbraco robot
|
||||
]]></key>
|
||||
<key alias="mailSubject">[%0%] Translation task for %1%</key>
|
||||
<key alias="noTranslators">No translator users found. Please create a translator user before you start sending content to translation</key>
|
||||
@@ -914,10 +919,10 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="translateTo">Translate to</key>
|
||||
<key alias="translationDone">Translation completed.</key>
|
||||
<key alias="translationDoneHelp">You can preview the pages, you've just translated, by clicking below. If the original page is found, you will get a comparison of the 2 pages.</key>
|
||||
<key alias="translationFailed">Translation failed, the xml file might be corrupt</key>
|
||||
<key alias="translationFailed">Translation failed, the XML file might be corrupt</key>
|
||||
<key alias="translationOptions">Translation options</key>
|
||||
<key alias="translator">Translator</key>
|
||||
<key alias="uploadTranslationXml">Upload translation xml</key>
|
||||
<key alias="uploadTranslationXml">Upload translation XML</key>
|
||||
</area>
|
||||
<area alias="treeHeaders">
|
||||
<key alias="cacheBrowser">Cache Browser</key>
|
||||
@@ -948,6 +953,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="stylesheets">Stylesheets</key>
|
||||
<key alias="templates">Templates</key>
|
||||
<key alias="xslt">XSLT Files</key>
|
||||
<key alias="analytics">Analytics</key>
|
||||
</area>
|
||||
<area alias="update">
|
||||
<key alias="updateAvailable">New update ready</key>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="es" intName="Spanish" localName="español" lcid="10" culture="es-ES">
|
||||
<creator>
|
||||
<name>The umbraco community</name>
|
||||
<link>http://umbraco.org/documentation/language-files</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Administrar hostnames</key>
|
||||
<key alias="auditTrail">Auditoría</key>
|
||||
<key alias="browse">Nodo de Exploración</key>
|
||||
<key alias="changeDocType">Cambiar tipo de documento</key>
|
||||
<key alias="copy">Copiar</key>
|
||||
<key alias="create">Crear</key>
|
||||
<key alias="createPackage">Crear Paquete</key>
|
||||
@@ -15,8 +16,6 @@
|
||||
<key alias="disable">Deshabilitar</key>
|
||||
<key alias="emptyTrashcan">Vaciar Papelera</key>
|
||||
<key alias="exportDocumentType">Exportar Documento (tipo)</key>
|
||||
<key alias="exportDocumentTypeAsCode">TRANSLATE ME: 'Export to .NET'</key>
|
||||
<key alias="exportDocumentTypeAsCode-Full">TRANSLATE ME: 'Export to .NET'</key>
|
||||
<key alias="importDocumentType">Importar Documento (tipo)</key>
|
||||
<key alias="importPackage">Importar Paquete</key>
|
||||
<key alias="liveEdit">Editar en lienzo</key>
|
||||
@@ -25,6 +24,7 @@
|
||||
<key alias="notify">Notificaciones</key>
|
||||
<key alias="protect">Acceso Público</key>
|
||||
<key alias="publish">Publicar</key>
|
||||
<key alias="unpublish">Unpublish</key>
|
||||
<key alias="refreshNode">Recargar Nodos</key>
|
||||
<key alias="republish">Republicar sitio completo</key>
|
||||
<key alias="rights">Permisos</key>
|
||||
@@ -35,21 +35,42 @@
|
||||
<key alias="toPublish">Enviar a publicación</key>
|
||||
<key alias="translate">Traducir</key>
|
||||
<key alias="update">Actualizar</key>
|
||||
<key alias="defaultValue">Default value</key>
|
||||
</area>
|
||||
<area alias="assignDomain">
|
||||
<key alias="permissionDenied">Permission denied.</key>
|
||||
<key alias="addNew">Añadir nuevo dominio</key>
|
||||
<key alias="remove">remove</key>
|
||||
<key alias="invalidNode">Invalid node.</key>
|
||||
<key alias="invalidDomain">Invalid domain format.</key>
|
||||
<key alias="duplicateDomain">Domain has already been assigned.</key>
|
||||
<key alias="language">Language</key>
|
||||
<key alias="domain">Dominio</key>
|
||||
<key alias="domainCreated">El nuevo dominio %0% ha sido creado</key>
|
||||
<key alias="domainDeleted">El dominio %0% ha sido borrado</key>
|
||||
<key alias="domainExists">El dominio'%0%' ya ha sido asignado</key>
|
||||
<key alias="domainHelp">p.ej.: tudominio.com, www.tudominio.com</key>
|
||||
<key alias="domainUpdated">El dominio %0% ha sido actualizado</key>
|
||||
<key alias="orEdit">Editar dominios actuales</key>
|
||||
<key alias="domainHelp">
|
||||
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
should be avoided. Better use the culture setting above.]]>
|
||||
</key>
|
||||
<key alias="inherit">Inherit</key>
|
||||
<key alias="setLanguage">Culture</key>
|
||||
<key alias="setLanguageHelp">
|
||||
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
|
||||
to the current node, unless a domain below applies too.]]>
|
||||
</key>
|
||||
<key alias="setDomains">Domains</key>
|
||||
</area>
|
||||
<area alias="auditTrails">
|
||||
<key alias="atViewingFor">Visualización de</key>
|
||||
</area>
|
||||
<area alias="buttons">
|
||||
<key alias="select">Select</key>
|
||||
<key alias="selectCurrentFolder">Select current folder</key>
|
||||
<key alias="somethingElse">Do something else</key>
|
||||
<key alias="bold">Negrita</key>
|
||||
<key alias="deindent">Cancelar Sangría del Párrafo </key>
|
||||
<key alias="formFieldInsert">Insertar campo de formulario</key>
|
||||
@@ -71,10 +92,31 @@
|
||||
<key alias="saveAndPublish">Guardar y publicar</key>
|
||||
<key alias="saveToPublish">Guardar y enviar para aprobación</key>
|
||||
<key alias="showPage">Previsualizar</key>
|
||||
<key alias="showPageDisabled">Preview is disabled because there's no template assigned</key>
|
||||
<key alias="styleChoose">Elegir estilo</key>
|
||||
<key alias="styleShow">Mostrar estilos</key>
|
||||
<key alias="tableInsert">Insertar tabla</key>
|
||||
</area>
|
||||
<area alias="changeDocType">
|
||||
<key alias="changeDocTypeInstruction">To change the document type for the selected content, first select from the list of valid types for this location.</key>
|
||||
<key alias="changeDocTypeInstruction2">Then confirm and/or amend the mapping of properties from the current type to the new, and click Save.</key>
|
||||
<key alias="contentRepublished">The content has been re-published.</key>
|
||||
<key alias="currentProperty">Current Property</key>
|
||||
<key alias="currentType">Current type</key>
|
||||
<key alias="docTypeCannotBeChanged">The document type cannot be changed, as there are no alternatives valid for this location.</key>
|
||||
<key alias="docTypeChanged">Document Type Changed</key>
|
||||
<key alias="mapProperties">Map Properties</key>
|
||||
<key alias="mapToProperty">Map to Property</key>
|
||||
<key alias="newTemplate">New Template</key>
|
||||
<key alias="newType">New Type</key>
|
||||
<key alias="none">none</key>
|
||||
<key alias="selectedContent">Content</key>
|
||||
<key alias="selectNewDocType">Select New Document Type</key>
|
||||
<key alias="successMessage">The document type of the selected content has been successfully changed to [new type] and the following properties mapped:</key>
|
||||
<key alias="to">to</key>
|
||||
<key alias="validationErrorPropertyWithMoreThanOneMapping">Could not complete property mapping as one or more properties have more than one mapping defined.</key>
|
||||
<key alias="validDocTypesNote">Only alternate types valid for the current location are displayed.</key>
|
||||
</area>
|
||||
<area alias="content">
|
||||
<key alias="about">Acerca de</key>
|
||||
<key alias="alias">Link alternativo</key>
|
||||
@@ -82,7 +124,10 @@
|
||||
<key alias="alternativeUrls">Vinculos Alternativos</key>
|
||||
<key alias="clickToEdit">Click para editar esta entrada</key>
|
||||
<key alias="createBy">Creado por</key>
|
||||
<key alias="createByDesc" version="7.0">Autor original</key>
|
||||
<key alias="updatedBy" version="7.0">Actualizado por</key>
|
||||
<key alias="createDate">Creado</key>
|
||||
<key alias="createDateDesc" version="7.0">Fecha/hora de creación del documento</key>
|
||||
<key alias="documentType">Tipo de Documento</key>
|
||||
<key alias="editing">Editando</key>
|
||||
<key alias="expireDate">Remover el</key>
|
||||
@@ -97,9 +142,11 @@
|
||||
<key alias="nodeName">Título de la página</key>
|
||||
<key alias="otherElements">Propiedades</key>
|
||||
<key alias="parentNotPublished">Este documento ha sido publicado pero no es visible porque el padre '%0%' no esta publicado</key>
|
||||
<key alias="parentNotPublishedAnomaly">Oops: this document is published but is not in the cache (internal error)</key>
|
||||
<key alias="publish">Publicar</key>
|
||||
<key alias="publishStatus">Estado de la Publicación</key>
|
||||
<key alias="releaseDate">Publicar el</key>
|
||||
<key alias="unpublishDate">Despublicar el</key>
|
||||
<key alias="removeDate">Fecha de Eliminación</key>
|
||||
<key alias="sortDone">El Orden esta actualizado</key>
|
||||
<key alias="sortHelp">Para organizar los nodos, simplemente arrastre los nodos o realice un clic en uno de los encabezados de columna. Puede seleccionar multiple nodos manteniendo presionados "Shift" o "Control" mientras selecciona</key>
|
||||
@@ -108,17 +155,28 @@
|
||||
<key alias="type">Tipo</key>
|
||||
<key alias="unPublish">No Publicar</key>
|
||||
<key alias="updateDate">Última actualización</key>
|
||||
<key alias="updateDateDesc" version="7.0">Fecha/hora este documento fue modificado</key>
|
||||
<key alias="uploadClear">Eliminar archivo</key>
|
||||
<key alias="urls">Vínculo al documento</key>
|
||||
<key alias="memberof">Member of group(s)</key>
|
||||
<key alias="notmemberof">Not a member of group(s)</key>
|
||||
<key alias="childItems" version="7.0">Child items</key>
|
||||
<key alias="target" version="7.0">Target</key>
|
||||
</area>
|
||||
<area alias="media">
|
||||
<key alias="clickToUpload">Click to upload</key>
|
||||
<key alias="dropFilesHere">Drop your files here...</key>
|
||||
</area>
|
||||
<area alias="create">
|
||||
<key alias="chooseNode">¿Dónde quieres crear el nuevo %0%</key>
|
||||
<key alias="createUnder">Crear debajo de</key>
|
||||
<key alias="updateData">Elije un tipo y un título</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[There are no allowed document types available. You must enable these in the settings section under <strong>"document types"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[There are no allowed media types available. You must enable these in the settings section under <strong>"media types"</strong>.]]></key>
|
||||
</area>
|
||||
<area alias="dashboard">
|
||||
<key alias="browser">Navega en tu sitio Web</key>
|
||||
<key alias="dontShowAgain">TRANSLATE ME: '- Hide'</key>
|
||||
<key alias="dontShowAgain">No volver a mostrar</key>
|
||||
<key alias="nothinghappens">Si Umbraco no se ha abierto tendrás que permitir ventanas emergentes para este sitio Web</key>
|
||||
<key alias="openinnew">se ha abierto en una nueva ventana</key>
|
||||
<key alias="restart">Reinicio</key>
|
||||
@@ -134,11 +192,11 @@
|
||||
<key alias="confirmEmptyTrashcan">Por favor seleccione esta casilla para confirmar la eliminación de %0% entrada(s)</key>
|
||||
<key alias="confirmlogout">Esta usted seguro?</key>
|
||||
<key alias="confirmSure">Esta usted Seguro?</key>
|
||||
<key alias="cut">TRANSLATE ME: 'Cut'</key>
|
||||
<key alias="cut">Cortar</key>
|
||||
<key alias="editdictionary">Editar entrada del Diccionario</key>
|
||||
<key alias="editlanguage">Editar idioma</key>
|
||||
<key alias="insertAnchor">Agregar enlace interno</key>
|
||||
<key alias="insertCharacter">TRANSLATE ME: 'Insert character'</key>
|
||||
<key alias="insertCharacter">Insertar caracter</key>
|
||||
<key alias="insertgraphicheadline">Insertar titular gráfico</key>
|
||||
<key alias="insertimage">Insertar imagen</key>
|
||||
<key alias="insertlink">Insertar enlace</key>
|
||||
@@ -149,7 +207,7 @@
|
||||
<key alias="linkinternal">Enlace interno</key>
|
||||
<key alias="linklocaltip">Al usar enlaces locales, insertar "#" delante del enlace</key>
|
||||
<key alias="linknewwindow">¿Abrir en nueva ventana?</key>
|
||||
<key alias="macroContainerSettings">TRANSLATE ME: 'Macro Settings'</key>
|
||||
<key alias="macroContainerSettings">Ajustes para la Macro</key>
|
||||
<key alias="macroDoesNotHaveProperties">Esta macro no contiene ninguna propiedad que pueda editar</key>
|
||||
<key alias="paste">Pegar</key>
|
||||
<key alias="permissionsEdit">Editar permisos para</key>
|
||||
@@ -158,7 +216,7 @@
|
||||
<key alias="recycleBinWarning">No podrá recuperar los items una vez sean borrados de la papelera</key>
|
||||
<key alias="regexSearchError"><![CDATA[El servicio web <a target='_blank' href='http://regexlib.com'>regexlib.com</a> está experimentando algunos problemas en estos momentos, de los cuales no somos responsables. Pedimos disculpas por las molestias.]]></key>
|
||||
<key alias="regexSearchHelp">Buscar una expresión regular para agregar validación a un campo de formulario. Ejemplo: 'correo electrónico', código postal "," url "</key>
|
||||
<key alias="removeMacro">TRANSLATE ME: 'Remove Macro'</key>
|
||||
<key alias="removeMacro">Eliminar macro</key>
|
||||
<key alias="requiredField">Campo obligatorio</key>
|
||||
<key alias="sitereindexed">El sitio ha sido reindexado</key>
|
||||
<key alias="siterepublished">Se ha actualizado la caché y se ha publicado el contenido del sitio web.</key>
|
||||
@@ -176,14 +234,24 @@
|
||||
<key alias="displayName"><![CDATA[nombre de la cultura
|
||||
]]></key>
|
||||
</area>
|
||||
<area alias="placeholders">
|
||||
<key alias="username">Introduzca su nombre de usuario</key>
|
||||
<key alias="password">Introduzca su contraseña</key>
|
||||
<key alias="nameentity">Nombre de %0%...</key>
|
||||
<key alias="entername">Introduzca un nombre ...</key>
|
||||
<key alias="search">Buscar ...</key>
|
||||
<key alias="filter">Filtrar ...</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
<key alias="allowedchildnodetypes">Tipos de nodos hijos permitidos</key>
|
||||
<key alias="contenttypecompositions">Document Type Compositions</key>
|
||||
<key alias="create">Crear</key>
|
||||
<key alias="deletetab">Borrar pestaña</key>
|
||||
<key alias="description">TRANSLATE ME: 'Description'</key>
|
||||
<key alias="description">Descripción</key>
|
||||
<key alias="newtab">Nueva pestaña</key>
|
||||
<key alias="tab">Pestaña</key>
|
||||
<key alias="thumbnail">TRANSLATE ME: 'Thumbnail'</key>
|
||||
<key alias="thumbnail">Miniatura</key>
|
||||
<key alias="hasListView">Enable list view</key>
|
||||
</area>
|
||||
<area alias="editdatatype">
|
||||
<key alias="addPrevalue">añadir prevalor</key>
|
||||
@@ -215,7 +283,7 @@
|
||||
<key alias="errorRegExpWithoutTab">Debe poner un formato correcto en %0%</key>
|
||||
</area>
|
||||
<area alias="errors">
|
||||
<key alias="codemirroriewarning">TRANSLATE ME: 'NOTE! Even though CodeMirror is enabled by configuration, it is disabled in Internet Explorer because it's not stable enough.'</key>
|
||||
<key alias="codemirroriewarning">NOTA: Aunque CodeMirror esté activado en los ajustes de configuracion, no se muestra en Internet Explorer debido a que no es lo suficientemente estable.'</key>
|
||||
<key alias="contentTypeAliasAndNameNotNull">Debe llenar el alias y el nombre en el propertytype</key>
|
||||
<key alias="filePermissionsError">Hay un problema de lectura y escritura al acceder a un archivo o carpeta</key>
|
||||
<key alias="missingTitle"><![CDATA[Por favor, introduzca un título
|
||||
@@ -239,6 +307,7 @@
|
||||
<area alias="general">
|
||||
<key alias="about">Acerca de</key>
|
||||
<key alias="action">Acción</key>
|
||||
<key alias="actions">Acciones</key>
|
||||
<key alias="add">Añadir</key>
|
||||
<key alias="alias">Alias</key>
|
||||
<key alias="areyousure">¿Está seguro?</key>
|
||||
@@ -268,7 +337,7 @@
|
||||
<key alias="edit">Editar</key>
|
||||
<key alias="edited">Editado</key>
|
||||
<key alias="elements">Elementos</key>
|
||||
<key alias="email">Email</key>
|
||||
<key alias="email">Mail</key>
|
||||
<key alias="error">Error</key>
|
||||
<key alias="findDocument">Buscar</key>
|
||||
<key alias="height">Altura</key>
|
||||
@@ -282,7 +351,7 @@
|
||||
<key alias="language">Idioma</key>
|
||||
<key alias="layout">Diseño</key>
|
||||
<key alias="loading">Cargando</key>
|
||||
<key alias="locked">TRANSLATE ME: 'Locked'</key>
|
||||
<key alias="locked">Bloqueado</key>
|
||||
<key alias="login">Iniciar sesión</key>
|
||||
<key alias="logoff">Cerrar sesión</key>
|
||||
<key alias="logout">Cerrar sesión</key>
|
||||
@@ -302,11 +371,11 @@
|
||||
<key alias="pleasewait">Un momento por favor...</key>
|
||||
<key alias="previous">Anterior</key>
|
||||
<key alias="properties">Propiedades</key>
|
||||
<key alias="reciept">Email para recibir los datos del formulario</key>
|
||||
<key alias="reciept">Mail para recibir los datos del formulario</key>
|
||||
<key alias="recycleBin">Papelera</key>
|
||||
<key alias="remaining">Restantes</key>
|
||||
<key alias="rename">Renombrar</key>
|
||||
<key alias="renew">TRANSLATE ME: 'Renew'</key>
|
||||
<key alias="renew">Renovar</key>
|
||||
<key alias="retry">Reintentar</key>
|
||||
<key alias="rights">Permisos</key>
|
||||
<key alias="search">Buscar</key>
|
||||
@@ -347,7 +416,7 @@
|
||||
<key alias="databaseHeader">Configuración de la base de datos</key>
|
||||
<key alias="databaseInstall"><![CDATA[Pulse el botón <strong> instalar </ strong> para instalar %0% la base de datos de Umbraco]]></key>
|
||||
<key alias="databaseInstallDone"><![CDATA[Se ha copiado Umbraco %0% a la base de datos. Pulse <strong>Próximo</strong> para continuar]]></key>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>¡No se ha encontrado ninguna base de datos! Mira si la información en la "connection string" del “web.config” es correcta.</p> <p>Para continuar, edite el "web.config" (bien sea usando Visual Studio o su editor de texto preferido), vaya al final del archivo y añada la cadena de conexión para la base de datos con el nombre (key) "umbracoDbDSN" y guarde el archivo. </p> <p>Pinche en <strong>reintentar</strong> cuando haya terminado.<br /><a href="http://umbraco.org/redir/installWebConfig" target="_blank">Pinche aquí para mayor información de como editar el web.config (en inglés)</a></p>]]></key>
|
||||
<key alias="databaseNotFound"><![CDATA[<p>¡No se ha encontrado ninguna base de datos! Mira si la información en la "connection string" del “web.config” es correcta.</p> <p>Para continuar, edite el "web.config" (bien sea usando Visual Studio o su editor de texto preferido), vaya al final del archivo y añada la cadena de conexión para la base de datos con el nombre (key) "umbracoDbDSN" y guarde el archivo. </p> <p>Pinche en <strong>reintentar</strong> cuando haya terminado.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">Pinche aquí para mayor información de como editar el web.config (en inglés)</a></p>]]></key>
|
||||
<key alias="databaseText"><![CDATA[Para completar este paso, debes conocer la información correspondiente a tu servidor de base de datos ("cadena de conexión").<br /> Por favor, contacta con tu ISP si es necesario. Si estás realizando la instalación en una máquina o servidor local, quizás necesites información de tu administrador de sistemas.]]></key>
|
||||
<key alias="databaseUpgrade"><![CDATA[<p> Pinche en <strong>actualizar</strong> para actualizar la base de datos a Umbraco %0%</p> <p> Ningún contenido será borrado de la base de datos y seguirá funcionando después de la actualización </p> ]]></key>
|
||||
<key alias="databaseUpgradeDone"><![CDATA[La base de datos ha sido actualizada a la versión 0%.<br />Pinche en <strong>Próximo</strong> para continuar. ]]></key>
|
||||
@@ -407,13 +476,23 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="displayName">Nombre de cultura</key>
|
||||
</area>
|
||||
<area alias="lockout">
|
||||
<key alias="lockoutWillOccur">TRANSLATE ME: 'You've been idle and logout will automatically occur in'</key>
|
||||
<key alias="renewSession">TRANSLATE ME: 'Renew now to save your work'</key>
|
||||
<key alias="lockoutWillOccur">No ha habido ninguna actividad y su sessión se cerrará en </key>
|
||||
<key alias="renewSession">Renovar su sessión para guardar sus cambios</key>
|
||||
</area>
|
||||
<area alias="login">
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="greeting0">Feliz Domingo</key>
|
||||
<key alias="greeting1">Feliz Lunes</key>
|
||||
<key alias="greeting2">Feliz Martes</key>
|
||||
<key alias="greeting3">Feliz Miércoles</key>
|
||||
<key alias="greeting4">Feliz Jueves</key>
|
||||
<key alias="greeting5">Feliz Viernes</key>
|
||||
<key alias="greeting6">Feliz Sábado</key>
|
||||
<key alias="instruction">Introduce abajo</key>
|
||||
<key alias="timeout">Session timed out</key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p> ]]></key>
|
||||
<key alias="topText">Bienvenido a umbraco, escribe tu nombre de usuario y clave en los campos de debajo:</key>
|
||||
</area>
|
||||
|
||||
<area alias="main">
|
||||
<key alias="dashboard">Panel de Administración</key>
|
||||
<key alias="sections">Secciones</key>
|
||||
@@ -429,7 +508,7 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="noNodeSelected">No ha seleccionado ningún nodo. Seleccione un nodo en la lista mostrada arriba antes the pinchar en 'continuar' (continue)</key>
|
||||
<key alias="notAllowedByContentType">No se puede colgar el nodo actual bajo el nodo elegido debido a su tipo</key>
|
||||
<key alias="notAllowedByPath">El nodo actual no puede moverse a ninguna de sus subpáginas</key>
|
||||
<key alias="notValid">TRANSLATE ME: 'The action isn't allowed since you have insufficient permissions on 1 or more child documents.'</key>
|
||||
<key alias="notValid">Acción no permitida. No tiene permisos suficientes para uno o más subnodos.'</key>
|
||||
</area>
|
||||
<area alias="notifications">
|
||||
<key alias="editNotifications">Edite su notificación para %0%</key>
|
||||
@@ -499,16 +578,16 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="publishHelp"><![CDATA[Pulsa en <em>aceptar</em> para publicar <strong>%0%</strong> y por lo tanto, hacer que su contenido esté disponible al público.<br/><br /> Puedes publicar esta página y todas sus subpáginas marcando <em>publicar todos los hijos</em> debajo. ]]></key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
<key alias="addExternal">TRANSLATE ME: 'Add external link'</key>
|
||||
<key alias="addInternal">TRANSLATE ME: 'Add internal link'</key>
|
||||
<key alias="addlink">TRANSLATE ME: 'Add'</key>
|
||||
<key alias="caption">TRANSLATE ME: 'Caption'</key>
|
||||
<key alias="internalPage">TRANSLATE ME: 'Internal page'</key>
|
||||
<key alias="linkurl">TRANSLATE ME: 'URL'</key>
|
||||
<key alias="modeDown">TRANSLATE ME: 'Move Down'</key>
|
||||
<key alias="modeUp">TRANSLATE ME: 'Move Up'</key>
|
||||
<key alias="newWindow">TRANSLATE ME: 'Open in new window'</key>
|
||||
<key alias="removeLink">TRANSLATE ME: 'Remove link'</key>
|
||||
<key alias="addExternal">Añadir un enlace externo</key>
|
||||
<key alias="addInternal">Añadir un enlace interno</key>
|
||||
<key alias="addlink">Añadir</key>
|
||||
<key alias="caption">Título</key>
|
||||
<key alias="internalPage">Página interna</key>
|
||||
<key alias="linkurl">Enlace</key>
|
||||
<key alias="modeDown">Bajar</key>
|
||||
<key alias="modeUp">Subir</key>
|
||||
<key alias="newWindow">Abrir en una nueva ventana</key>
|
||||
<key alias="removeLink">Quitar el enlace</key>
|
||||
</area>
|
||||
<area alias="rollback">
|
||||
<key alias="currentVersion">Versión actual</key>
|
||||
@@ -535,6 +614,8 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="statistics">Estadísticas</key>
|
||||
<key alias="translation">Traducción</key>
|
||||
<key alias="users">Usuarios</key>
|
||||
<key alias="help" version="7.0">Ayuda</key>
|
||||
<key alias="analytics">Analytics</key>
|
||||
</area>
|
||||
<area alias="settings">
|
||||
<key alias="defaulttemplate">Plantilla por defecto</key>
|
||||
@@ -548,6 +629,8 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="tab">Pestaña</key>
|
||||
<key alias="tabname">Nombre de la pestaña</key>
|
||||
<key alias="tabs">Pestañas</key>
|
||||
<key alias="masterDocumentType">Tipo de documento Maestro</key>
|
||||
<key alias="createMatchingTemplate">Crear template correspondiente</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortDone">Ordenación completa.</key>
|
||||
@@ -661,7 +744,7 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="mailBody"><![CDATA[
|
||||
Hola %0%.
|
||||
|
||||
Este email se ha generado automáticamente para informale que %2% ha solicitado que el documento '%1%' sea traducido en '%5%'.
|
||||
Este mail se ha generado automáticamente para informale que %2% ha solicitado que el documento '%1%' sea traducido en '%5%'.
|
||||
|
||||
Para editarlo, vaya a la dirección http://%3%/translation/details.aspx?id=%4% o inicie la sesión en umbraco y vaya a http://%3% para ver las tareas pendientes de traducir.
|
||||
|
||||
@@ -693,8 +776,8 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="datatype">Tipos de datos</key>
|
||||
<key alias="dictionary">Diccionario</key>
|
||||
<key alias="installedPackages">Paquetes instalados</key>
|
||||
<key alias="installSkin">TRANSLATE ME: 'Install skin'</key>
|
||||
<key alias="installStarterKit">TRANSLATE ME: 'Install starter kit'</key>
|
||||
<key alias="installSkin">Instalar skin</key>
|
||||
<key alias="installStarterKit">Instalar starter kit</key>
|
||||
<key alias="languages">Idiomas</key>
|
||||
<key alias="localPackage">Instalar paquete local</key>
|
||||
<key alias="macros">Macros</key>
|
||||
@@ -710,7 +793,7 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="repositories">Instalar desde repositorio</key>
|
||||
<key alias="runway">Instalar pasarela</key>
|
||||
<key alias="runwayModules">Módulos pasarela</key>
|
||||
<key alias="scripting">TRANSLATE ME: 'Scripting Files'</key>
|
||||
<key alias="scripting">Ficheros de script</key>
|
||||
<key alias="scripts">Scripts</key>
|
||||
<key alias="stylesheets">Hojas de estilo</key>
|
||||
<key alias="templates">Plantillas</key>
|
||||
@@ -725,8 +808,10 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<area alias="user">
|
||||
<key alias="administrators">Administrador</key>
|
||||
<key alias="categoryField">Campo de categoria</key>
|
||||
<key alias="changePassword">TRANSLATE ME: 'Change Your Password'</key>
|
||||
<key alias="changePasswordDescription">TRANSLATE ME: 'You can change your password for accessing the Umbraco Back Office by filling out the form below and click the 'Change Password' button'</key>
|
||||
<key alias="changePassword">Cambiar contraseña</key>
|
||||
<key alias="newPassword">Change Your Password</key>
|
||||
<key alias="confirmNewPassword">Confirm new password</key>
|
||||
<key alias="changePasswordDescription">Puede cambiar su contraseña para acceder al 'back office' de Umbraco rellenando el siguiente formulario y haciendo clic en el botón 'Cambiar contraseña'</key>
|
||||
<key alias="contentChannel">Canal de contenido</key>
|
||||
<key alias="descriptionField">Campo descriptivo</key>
|
||||
<key alias="disabled">Deshabilitar usuario</key>
|
||||
@@ -738,13 +823,16 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="mediastartnode">Nodo de comienzo en la libreria de medios</key>
|
||||
<key alias="modules">Secciones</key>
|
||||
<key alias="noConsole">Deshabilitar acceso a Umbraco</key>
|
||||
<key alias="password">Password</key>
|
||||
<key alias="passwordChanged">TRANSLATE ME: 'Your password has been changed!'</key>
|
||||
<key alias="passwordConfirm">TRANSLATE ME: 'Please confirm the new password'</key>
|
||||
<key alias="passwordEnterNew">TRANSLATE ME: 'Enter your new password'</key>
|
||||
<key alias="passwordIsBlank">TRANSLATE ME: 'Your new password cannot be blank!'</key>
|
||||
<key alias="passwordIsDifferent">TRANSLATE ME: 'There was a difference between the new password and the confirmed password. Please try again!'</key>
|
||||
<key alias="passwordMismatch">TRANSLATE ME: 'The confirmed password doesn't match the new password!'</key>
|
||||
<key alias="password">Contraseña</key>
|
||||
<key alias="resetPassword">Reset password</key>
|
||||
<key alias="passwordChanged">Su contraseña ha sido cambiada</key>
|
||||
<key alias="passwordConfirm">Por favor confirme su nueva contraseña</key>
|
||||
<key alias="passwordEnterNew">Introduzca su nueva contraseña</key>
|
||||
<key alias="passwordIsBlank">La nueva contraseña no puede estar vacía</key>
|
||||
<key alias="passwordCurrent">Current password</key>
|
||||
<key alias="passwordInvalid">Invalid current password</key>
|
||||
<key alias="passwordIsDifferent">La nueva contraseña no coincide con la contraseña de confirmación. Por favor, vuela a intentarlo!'</key>
|
||||
<key alias="passwordMismatch">La contraseña de confirmación no coincide con la nueva contraseña!'</key>
|
||||
<key alias="permissionReplaceChildren">Reemplazar los permisos de los nodos hijo</key>
|
||||
<key alias="permissionSelectedPages">Estas modificando los permisos para las páginas:</key>
|
||||
<key alias="permissionSelectPages">Selecciona las páginas para modificar sus permisos</key>
|
||||
@@ -755,5 +843,8 @@ However, Runway offers an easy foundation based on best practices to get you sta
|
||||
<key alias="usertype">Tipo de usuario</key>
|
||||
<key alias="userTypes">Tipos de usuarios</key>
|
||||
<key alias="writer">Redactor</key>
|
||||
<key alias="yourProfile" version="7.0">Your profile</key>
|
||||
<key alias="yourHistory" version="7.0">Your recent history</key>
|
||||
<key alias="sessionExpires" version="7.0">Session expires in</key>
|
||||
</area>
|
||||
</language>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="fr" intName="French" localName="français" lcid="12" culture="fr-FR">
|
||||
<creator>
|
||||
<name>The umbraco community</name>
|
||||
<link>http://umbraco.org/documentation/language-files</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Gérer les noms d'hôtes</key>
|
||||
@@ -420,7 +420,7 @@
|
||||
<p>Pour poursuivre, éditez le fichier "web.config" (avec Visual Studio ou votre éditeur de texte favori), scrollez jusqu'en bas, ajoutez une "connection string" dans la ligne "umbracoDbDSN" et sauvegardez votre fichier.</p>
|
||||
<p>
|
||||
Cliquez sur le bouton <strong>Réessayer</strong> lorsque cela est fait.
|
||||
<br /><a href="http://umbraco.org/redir/installWebConfig" target="_blank">
|
||||
<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">
|
||||
Plus d'informations sur l'édition du fichier web.config ici.</a></p>]]></key>
|
||||
<key alias="databaseText"><![CDATA[Pour effectuer cette étape, vous devez d'abord connaître des informations de votre serveur de base de données ("connection string").<br />
|
||||
Contactez votre administrateur système si nécessaire.
|
||||
@@ -545,7 +545,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
|
||||
<key alias="greeting6">Joyeux samedi</key>
|
||||
<key alias="instruction">Connectez-vous ci-dessous</key>
|
||||
<key alias="timeout">La session a expiré</key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p> ]]></key>
|
||||
</area>
|
||||
<area alias="main">
|
||||
<key alias="dashboard">Tableau de bord</key>
|
||||
@@ -751,6 +751,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
|
||||
<key alias="contentTypeUses">Ce type de contenu utilise</key>
|
||||
<key alias="asAContentMasterType">en tant que type de contenu master, les onglets du type de contenu master ne sont pas affichés et peuvent seulement être modifiés dans le type de contenu master lui-même.</key>
|
||||
<key alias="noPropertiesDefinedOnTab">Aucune propriétés définies dans cet onglet. Cliquez sur le lien "Ajouter une nouvelle propriété" en haut pour créer une nouvelle propriété.</key>
|
||||
<key alias="masterDocumentType">Type de contenu parent</key>
|
||||
<key alias="createMatchingTemplate">Créer le template correspondant</key>
|
||||
</area>
|
||||
<area alias="sort">
|
||||
<key alias="sortDone">Tri achevé.</key>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="he" intName="Hebrew (Israel)" localName="Hebrew" lcid="" culture="he-IL">
|
||||
<creator>
|
||||
<name>Umbraco Hebrew 2011</name>
|
||||
<link>http://umbraco.org</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">נהל שמות מתחם</key>
|
||||
@@ -354,7 +354,7 @@
|
||||
<p>To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "umbracoDbDSN" and save the file. </p>
|
||||
<p>
|
||||
Click the <strong>retry</strong> button when
|
||||
done.<br /><a href="http://umbraco.org/redir/installWebConfig" target="_blank">
|
||||
done.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank">
|
||||
More information on editing web.config here.</a></p>]]></key>
|
||||
<key alias="databaseText"><![CDATA[To complete this step, you must know some information regarding your database server ("connection string").<br />
|
||||
Please contact your ISP if necessary.
|
||||
@@ -469,7 +469,7 @@ To manage your website, simply open the umbraco back office and start adding con
|
||||
<key alias="renewSession">יש לבצע חידוש פעילות על מנת לשמור על התוכן</key>
|
||||
</area>
|
||||
<area alias="login">
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p> ]]></key>
|
||||
<key alias="topText">ברוכים הבאים לאומברקו, יש להזין שם משתמש וסיסמה בשדות למטה:</key>
|
||||
</area>
|
||||
<area alias="main">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<language alias="it" intName="Italian" localName="italiano" lcid="16" culture="it-IT">
|
||||
<creator>
|
||||
<name>The umbraco community</name>
|
||||
<link>http://umbraco.org/documentation/language-files</link>
|
||||
<name>The Umbraco community</name>
|
||||
<link>http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files</link>
|
||||
</creator>
|
||||
<area alias="actions">
|
||||
<key alias="assignDomain">Gestisci hostnames</key>
|
||||
@@ -266,7 +266,7 @@
|
||||
<key alias="findDocument">Trova</key>
|
||||
<key alias="folder">Cartella</key>
|
||||
<key alias="height">Altezza</key>
|
||||
<key alias="help">Aiuto</key>
|
||||
<key alias="help">Guida</key>
|
||||
<key alias="icon">Icona</key>
|
||||
<key alias="import">Importa</key>
|
||||
<key alias="innerMargin"><![CDATA[Margine interno (inner margin)]]></key>
|
||||
@@ -343,7 +343,7 @@
|
||||
<key alias="databaseInstallDone"><![CDATA[Umbraco %0% è stato copiato nel tuo database. Premi <strong>Avanti</strong> per proseguire.]]></key>
|
||||
<key alias="databaseNotFound">
|
||||
<![CDATA[<p>Database non trovato! Perfavore, controlla che le informazioni della stringa di connessione nel file "web.config" siano corrette.</p>
|
||||
<p>Per procedere, edita il file "web.config" (utilizzando Visual Studio o l'editor di testo che preferisci), scorri in basso, aggiungi la stringa di connessione per il database chiamato "umbracoDbDSN" e salva il file.</p><p>Clicca il tasto <strong>riprova</strong> quando hai finito.<br /><a href="http://umbraco.org/redir/installWebConfig" target="_blank"> Maggiori dettagli per la modifica del file web.config qui.</a></p>]]>
|
||||
<p>Per procedere, edita il file "web.config" (utilizzando Visual Studio o l'editor di testo che preferisci), scorri in basso, aggiungi la stringa di connessione per il database chiamato "umbracoDbDSN" e salva il file.</p><p>Clicca il tasto <strong>riprova</strong> quando hai finito.<br /><a href="http://our.umbraco.org/documentation/Using-Umbraco/Config-files/webconfig7" target="_blank"> Maggiori dettagli per la modifica del file web.config qui.</a></p>]]>
|
||||
</key>
|
||||
<key alias="databaseText"><![CDATA[Per completare questo passaggio, devi conoscere alcune informazioni riguardanti il tuo database server ("connection string"). Se è necessario contatta il tuo ISP per reperire le informazioni necessarie. Se stai effettuando l'installazione in locale o su un server, puoi richiederle al tuo amministratore di sistema]]></key>
|
||||
<key alias="databaseUpgrade"><![CDATA[<p>Premi il tasto <strong>aggiorna</strong> per aggiornare il database ad Umbraco %0%</p><p>Non preoccuparti, il contenuto non verrà perso e tutto continuerà a funzionare dopo l'aggiornamento!</p>]]></key>
|
||||
@@ -428,7 +428,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i
|
||||
<key alias="renewSession">Riconnetti adesso per salvare il tuo lavoro</key>
|
||||
</area>
|
||||
<area alias="login">
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.com" style="text-decoration: none" target="_blank">umbraco.com</a></p> ]]></key>
|
||||
<key alias="topText">Benvenuti in Umbraco, digita il tuo username e la tua password nelle caselle seguenti:</key>
|
||||
</area>
|
||||
<area alias="main">
|
||||
@@ -630,7 +630,7 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i
|
||||
<key alias="contentTypeTabCreated">Tab creata</key>
|
||||
<key alias="contentTypeTabDeleted">Tab eliminata</key>
|
||||
<key alias="contentTypeTabDeletedText">Tab con id: %0% eliminata</key>
|
||||
<key alias="contentUnpublished">Contenuto non pubblicato</key>
|
||||
<key alias="contentUnpublished">Contenuto non pubblicare</key>
|
||||
<key alias="cssErrorHeader"><![CDATA[Foglio di stile non salvato]]></key>
|
||||
<key alias="cssSavedHeader"><![CDATA[Foglio di stile salvato]]></key>
|
||||
<key alias="cssSavedText"><![CDATA[Foglio di stile salvato correttamente]]></key>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user