diff --git a/.gitignore b/.gitignore index 2fcab792e3..7f0afcdce1 100644 --- a/.gitignore +++ b/.gitignore @@ -145,4 +145,6 @@ build/ui-docs.zip build/csharp-docs.zip build/msbuild.log .vs/ -src/packages/ \ No newline at end of file +src/packages/ +build/tools/ +src/PrecompiledWeb/* diff --git a/build/Build.bat b/build/Build.bat index 17975d81e1..9935f1e624 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -160,18 +160,61 @@ CALL InstallGit.cmd :: but the path setting is lost due to SETLOCAL SET PATH="C:\Program Files (x86)\Git\cmd";"C:\Program Files\Git\cmd";%PATH% +SET toolsFolder=%CD%\tools\ +IF NOT EXIST "%toolsFolder%" ( + MD tools +) + +SET nuGetExecutable=%CD%\tools\nuget.exe +IF NOT EXIST "%nuGetExecutable%" ( + ECHO Getting NuGet so we can fetch some tools + ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable% + powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')" +) + +:: We need 7za.exe for BuildBelle.bat +IF NOT EXIST "%toolsFolder%7za.exe" ( + ECHO 7zip not found - fetching now + "%nuGetExecutable%" install 7-Zip.CommandLine -OutputDirectory tools -Verbosity quiet +) + +:: We need vswhere.exe for VS2017+ +IF NOT EXIST "%toolsFolder%vswhere.exe" ( + ECHO vswhere not found - fetching now + "%nuGetExecutable%" install vswhere -OutputDirectory tools -Verbosity quiet +) + +:: Put 7za.exe and vswhere.exe in a predictable path (not version specific) +FOR /f "delims=" %%A in ('dir "%toolsFolder%7-Zip.CommandLine.*" /b') DO SET "sevenZipExePath=%toolsFolder%%%A\" +MOVE "%sevenZipExePath%tools\7za.exe" "%toolsFolder%7za.exe" + +FOR /f "delims=" %%A in ('dir "%toolsFolder%vswhere.*" /b') DO SET "vswhereExePath=%toolsFolder%%%A\" +MOVE "%vswhereExePath%tools\vswhere.exe" "%toolsFolder%vswhere.exe" + ECHO. ECHO Making sure we have a web.config IF NOT EXIST "%CD%\..\src\Umbraco.Web.UI\web.config" COPY "%CD%\..\src\Umbraco.Web.UI\web.Template.config" "%CD%\..\src\Umbraco.Web.UI\web.config" +for /f "usebackq tokens=1* delims=: " %%i in (`"%CD%\tools\vswhere.exe" -latest -requires Microsoft.Component.MSBuild`) do ( + if /i "%%i"=="installationPath" set InstallDir=%%j +) + +SET VSWherePath="%InstallDir%\MSBuild" + +ECHO. +ECHO Visual Studio is installed in: %InstallDir% + +SET MSBUILDPATH=C:\Program Files (x86)\MSBuild\14.0\Bin +SET MSBUILD="%MSBUILDPATH%\MsBuild.exe" + ECHO. ECHO Reporting NuGet version -"%CD%\..\src\.nuget\NuGet.exe" help | findstr "^NuGet Version:" +"%nuGetExecutable%" help | findstr "^NuGet Version:" ECHO. ECHO Restoring NuGet packages ECHO Into %nuGetFolder% -"%CD%\..\src\.nuget\NuGet.exe" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%" +"%nuGetExecutable%" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%" IF ERRORLEVEL 1 GOTO :error ECHO. @@ -187,6 +230,7 @@ ECHO. /p:BUILD_NUMBER=%BUILD% ^ /p:BUILD_TESTS=%TESTS% ^ /p:NugetPackagesDirectory="%nuGetFolder%" ^ + /p:VSWherePath="%VSWherePath%" ^ /consoleloggerparameters:Summary;ErrorsOnly ^ /fileLogger IF ERRORLEVEL 1 GOTO error diff --git a/build/BuildBelle.bat b/build/BuildBelle.bat index 8a07ee380a..78b7736c2b 100644 --- a/build/BuildBelle.bat +++ b/build/BuildBelle.bat @@ -1,33 +1,59 @@ @ECHO OFF SETLOCAL + :: SETLOCAL is on, so changes to the path not persist to the actual user's path -SET release=%1 -ECHO Installing Npm NuGet Package - -SET nuGetFolder=%CD%\..\src\packages\ -ECHO Configured packages folder: %nuGetFolder% +SET toolsFolder=%CD%\tools\ ECHO Current folder: %CD% -%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet +SET nodeFileName=node-v6.9.1-win-x86.7z +SET nodeExtractFolder=%toolsFolder%node.js.691 -for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\" -for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\" +IF NOT EXIST "%nodeExtractFolder%" ( + ECHO Downloading http://nodejs.org/dist/v6.9.1/%nodeFileName% to %toolsFolder%%nodeFileName% + powershell -Command "(New-Object Net.WebClient).DownloadFile('http://nodejs.org/dist/v6.9.1/%nodeFileName%', '%toolsFolder%%nodeFileName%')" + ECHO Extracting %nodeFileName% to %nodeExtractFolder% + "%toolsFolder%\7za.exe" x "%toolsFolder%\%nodeFileName%" -o"%nodeExtractFolder%" -aos > nul +) +FOR /f "delims=" %%A in ('dir "%nodeExtractFolder%\node*" /b') DO SET "nodePath=%nodeExtractFolder%\%%A" -ECHO Adding Npm and Node to path -REM SETLOCAL is on, so changes to the path not persist to the actual user's path -PATH=%npmPath%;%nodePath%;%PATH% -SET buildFolder=%CD% +SET nuGetExecutable=%CD%\tools\nuget.exe +IF NOT EXIST "%nuGetExecutable%" ( + ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable% + powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')" +) -ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\ -CD %CD%\..\src\Umbraco.Web.UI.Client\ +SET drive=%CD:~0,2% +SET nuGetFolder=%drive%\packages\ +FOR /f "delims=" %%A in ('dir "%nuGetFolder%npm.*" /b') DO SET "npmPath=%nuGetFolder%%%A\" -ECHO Do npm install and the grunt build of Belle -call npm cache clean --quiet -call npm install --quiet -call npm install -g grunt-cli --quiet -call npm install -g bower --quiet -call grunt build --buildversion=%release% +IF [%npmPath%] == [] GOTO :installnpm +IF NOT [%npmPath%] == [] GOTO :build -ECHO Move back to the build folder -CD %buildFolder% \ No newline at end of file +:installnpm + ECHO Downloading npm + ECHO Configured packages folder: %nuGetFolder% + ECHO Installing Npm NuGet Package + "%nuGetExecutable%" install Npm -OutputDirectory %nuGetFolder% -Verbosity detailed + REM Ensures that we look for the just downloaded NPM, not whatever the user has installed on their machine + FOR /f "delims=" %%A in ('dir %nuGetFolder%npm.* /b') DO SET "npmPath=%nuGetFolder%%%A\" + GOTO :build + +:build + ECHO Adding Npm and Node to path + REM SETLOCAL is on, so changes to the path not persist to the actual user's path + PATH="%npmPath%";"%nodePath%";%PATH% + SET buildFolder=%CD% + + ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\ + CD %CD%\..\src\Umbraco.Web.UI.Client\ + + ECHO Do npm install and the grunt build of Belle + call npm cache clean --quiet + call npm install --quiet + call npm install -g grunt-cli --quiet + call npm install -g bower --quiet + call grunt build --buildversion=%release% + + ECHO Move back to the build folder + CD "%buildFolder%" \ No newline at end of file diff --git a/build/BuildDocs.ps1 b/build/BuildDocs.ps1 index dcb3a85cc1..7b13f98ca4 100644 --- a/build/BuildDocs.ps1 +++ b/build/BuildDocs.ps1 @@ -57,6 +57,20 @@ $IndexPath = "../src/umbraco.web.ui.client/docs/api/index.html" # Build the solution in debug mode $SolutionPath = Join-Path -Path $SolutionRoot -ChildPath "umbraco.sln" + +# Go get nuget.exe if we don't hae it +$NuGet = "$ToolsRoot\nuget.exe" +$FileExists = Test-Path $NuGet +If ($FileExists -eq $False) { + Write-Host "Retrieving nuget.exe..." + $SourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" + Invoke-WebRequest $SourceNugetExe -OutFile $NuGet +} + +#restore nuget packages +Write-Host "Restoring nuget packages..." +& $NuGet restore $SolutionPath + & $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount /t:Clean if (-not $?) { diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index 99448168c8..89170aa492 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -1,6 +1,6 @@ - + UmbracoCms.Core 7.0.0 Umbraco Cms Core Binaries @@ -38,10 +38,10 @@ - + - - + + diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index 22bbf5a58d..f376ec6b24 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -1,6 +1,6 @@ - + UmbracoCms 7.0.0 Umbraco Cms @@ -16,7 +16,7 @@ umbraco - + diff --git a/build/NuSpecs/tools/Web.config.install.xdt b/build/NuSpecs/tools/Web.config.install.xdt index cbb60bb949..4e4e056fb4 100644 --- a/build/NuSpecs/tools/Web.config.install.xdt +++ b/build/NuSpecs/tools/Web.config.install.xdt @@ -330,6 +330,7 @@ + @@ -383,6 +384,10 @@ + + + + diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs index 9f1c61ec09..c84a054fa1 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs @@ -116,6 +116,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings internal CommaDelimitedConfigurationElement DisallowedUploadFiles { get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); } + } + + [ConfigurationProperty("allowedUploadFiles")] + internal CommaDelimitedConfigurationElement AllowedUploadFiles + { + get { return GetOptionalDelimitedElement("allowedUploadFiles", new string[0]); } } [ConfigurationProperty("cloneXmlContent")] @@ -263,6 +269,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings IEnumerable IContentSection.DisallowedUploadFiles { get { return DisallowedUploadFiles; } + } + + IEnumerable IContentSection.AllowedUploadFiles + { + get { return AllowedUploadFiles; } } bool IContentSection.CloneXmlContent diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs new file mode 100644 index 0000000000..a4f182b373 --- /dev/null +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs @@ -0,0 +1,19 @@ +using System.Linq; + +namespace Umbraco.Core.Configuration.UmbracoSettings +{ + public static class ContentSectionExtensions + { + /// + /// Determines if file extension is allowed for upload based on (optional) white list and black list + /// held in settings. + /// Allow upload if extension is whitelisted OR if there is no whitelist and extension is NOT blacklisted. + /// + public static bool IsFileAllowedForUpload(this IContentSection contentSection, string extension) + { + return contentSection.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)) || + (contentSection.AllowedUploadFiles.Any() == false && + contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs index 56f6d76f49..3c4e9df48d 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs @@ -49,6 +49,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings IEnumerable DisallowedUploadFiles { get; } + IEnumerable AllowedUploadFiles { get; } + bool CloneXmlContent { get; } bool GlobalPreviewStorageEnabled { get; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IRepository.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IRepository.cs index 052c23edd5..7559f090c0 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IRepository.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IRepository.cs @@ -8,6 +8,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings Guid Id { get; } string RepositoryUrl { get; } string WebServiceUrl { get; } - bool HasCustomWebServiceUrl { get; } + bool HasCustomWebServiceUrl { get; } + string RestApiUrl { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryConfigExtensions.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryConfigExtensions.cs new file mode 100644 index 0000000000..e2c4283dc6 --- /dev/null +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryConfigExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Linq; + +namespace Umbraco.Core.Configuration.UmbracoSettings +{ + public static class RepositoryConfigExtensions + { + //Our package repo + private static readonly Guid RepoGuid = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66"); + + public static IRepository GetDefault(this IRepositoriesSection repos) + { + var found = repos.Repositories.FirstOrDefault(x => x.Id == RepoGuid); + if (found == null) + throw new InvalidOperationException("No default package repository found with id " + RepoGuid); + return found; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryElement.cs index b7a1157c40..a249be2ee3 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/RepositoryElement.cs @@ -38,9 +38,16 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { var prop = Properties["webserviceurl"]; - var repoUrl = this[prop] as ConfigurationElement; - return (repoUrl != null && repoUrl.ElementInformation.IsPresent); + return (string) prop.DefaultValue != (string) this[prop]; } } + + [ConfigurationProperty("restapiurl", DefaultValue = "https://our.umbraco.org/webapi/packages/v1")] + public string RestApiUrl + { + get { return (string)base["restapiurl"]; } + set { base["restapiurl"] = value; } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Constants-System.cs b/src/Umbraco.Core/Constants-System.cs index 74ffcef8fc..bc4151c7d9 100644 --- a/src/Umbraco.Core/Constants-System.cs +++ b/src/Umbraco.Core/Constants-System.cs @@ -24,7 +24,6 @@ public const string UmbracoConnectionName = "umbracoDbDSN"; public const string UmbracoMigrationName = "Umbraco"; - } - + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/CoreRuntimeComponent.cs b/src/Umbraco.Core/CoreRuntimeComponent.cs index 520efef53a..0496b83fcd 100644 --- a/src/Umbraco.Core/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/CoreRuntimeComponent.cs @@ -81,7 +81,7 @@ namespace Umbraco.Core composition.Container.RegisterSingleton(f => { if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled) - return new ConfigServerRegistrar(UmbracoConfig.For.UmbracoSettings()); + return new ConfigServerRegistrar(UmbracoConfig.For.UmbracoSettings(), f.GetInstance()); if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"])) return new SingleServerRegistrar(f.GetInstance()); return new DatabaseServerRegistrar( diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs index 7815747f18..63562eb53e 100644 --- a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs @@ -1,85 +1,177 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Security.Permissions; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Events { - /// - /// Event args for a strongly typed object that can support cancellation - /// - /// - [HostProtection(SecurityAction.LinkDemand, SharedState = true)] - public class CancellableObjectEventArgs : CancellableEventArgs, IEquatable> - { - public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + /// + /// Used as a base class for the generic type CancellableObjectEventArgs{T} so that we can get direct 'object' access to the underlying EventObject + /// + [HostProtection(SecurityAction.LinkDemand, SharedState = true)] + public abstract class CancellableObjectEventArgs : CancellableEventArgs + { + protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(canCancel, messages, additionalData) - { + { EventObject = eventObject; } - public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages) + protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages eventMessages) : base(canCancel, eventMessages) { EventObject = eventObject; } - public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages) + protected CancellableObjectEventArgs(object eventObject, EventMessages eventMessages) : this(eventObject, true, eventMessages) { } + protected CancellableObjectEventArgs(object eventObject, bool canCancel) + : base(canCancel) + { + EventObject = eventObject; + } + + protected CancellableObjectEventArgs(object eventObject) + : this(eventObject, true) + { + } + + /// + /// Returns the object relating to the event + /// + /// + /// This is protected so that inheritors can expose it with their own name + /// + internal object EventObject { get; set; } + + } + + /// + /// Event args for a strongly typed object that can support cancellation + /// + /// + [HostProtection(SecurityAction.LinkDemand, SharedState = true)] + public class CancellableObjectEventArgs : CancellableObjectEventArgs, IEquatable> + { + public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + : base(eventObject, canCancel, messages, additionalData) + { + } + + public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages) + : base(eventObject, canCancel, eventMessages) + { + } + + public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages) + : base(eventObject, eventMessages) + { + } + public CancellableObjectEventArgs(T eventObject, bool canCancel) - : base(canCancel) - { - EventObject = eventObject; - } + : base(eventObject, canCancel) + { + } - public CancellableObjectEventArgs(T eventObject) - : this(eventObject, true) - { - } + public CancellableObjectEventArgs(T eventObject) + : base(eventObject) + { + } - /// - /// Returns the object relating to the event - /// - /// - /// This is protected so that inheritors can expose it with their own name - /// - protected T EventObject { get; set; } + /// + /// Returns the object relating to the event + /// + /// + /// This is protected so that inheritors can expose it with their own name + /// + protected new T EventObject + { + get { return (T) base.EventObject; } + set { base.EventObject = value; } + } - public bool Equals(CancellableObjectEventArgs other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject); - } + public bool Equals(CancellableObjectEventArgs other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject); + } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((CancellableObjectEventArgs) obj); - } + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((CancellableObjectEventArgs)obj); + } - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ EqualityComparer.Default.GetHashCode(EventObject); - } - } + public override int GetHashCode() + { + unchecked + { + return (base.GetHashCode() * 397) ^ EqualityComparer.Default.GetHashCode(EventObject); + } + } - public static bool operator ==(CancellableObjectEventArgs left, CancellableObjectEventArgs right) - { - return Equals(left, right); - } + public static bool operator ==(CancellableObjectEventArgs left, CancellableObjectEventArgs right) + { + return Equals(left, right); + } - public static bool operator !=(CancellableObjectEventArgs left, CancellableObjectEventArgs right) - { - return !Equals(left, right); - } - } + public static bool operator !=(CancellableObjectEventArgs left, CancellableObjectEventArgs right) + { + return !Equals(left, right); + } + } + + [HostProtection(SecurityAction.LinkDemand, SharedState = true)] + public class CancellableEnumerableObjectEventArgs : CancellableObjectEventArgs>, IEquatable> + { + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + : base(eventObject, canCancel, messages, additionalData) + { } + + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages eventMessages) + : base(eventObject, canCancel, eventMessages) + { } + + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, EventMessages eventMessages) + : base(eventObject, eventMessages) + { } + + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel) + : base(eventObject, canCancel) + { } + + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject) + : base(eventObject) + { } + + public bool Equals(CancellableEnumerableObjectEventArgs other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return EventObject.SequenceEqual(other.EventObject); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((CancellableEnumerableObjectEventArgs)obj); + } + + public override int GetHashCode() + { + return HashCodeHelper.GetHashCode(EventObject); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Events/DeleteEventArgs.cs b/src/Umbraco.Core/Events/DeleteEventArgs.cs index df13363b95..d0a4f024e1 100644 --- a/src/Umbraco.Core/Events/DeleteEventArgs.cs +++ b/src/Umbraco.Core/Events/DeleteEventArgs.cs @@ -1,9 +1,14 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Umbraco.Core.Events { - public class DeleteEventArgs : CancellableObjectEventArgs>, IEquatable>, IDeletingMediaFilesEventArgs + [SupersedeEvent(typeof(SaveEventArgs<>))] + [SupersedeEvent(typeof(PublishEventArgs<>))] + [SupersedeEvent(typeof(MoveEventArgs<>))] + [SupersedeEvent(typeof(CopyEventArgs<>))] + public class DeleteEventArgs : CancellableEnumerableObjectEventArgs, IEquatable>, IDeletingMediaFilesEventArgs { /// /// Constructor accepting multiple entities that are used in the delete operation @@ -106,7 +111,7 @@ namespace Umbraco.Core.Events { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return base.Equals(other) && MediaFilesToDelete.Equals(other.MediaFilesToDelete); + return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete); } public override bool Equals(object obj) diff --git a/src/Umbraco.Core/Events/ImportEventArgs.cs b/src/Umbraco.Core/Events/ImportEventArgs.cs index dcecf5c36b..892149c0a2 100644 --- a/src/Umbraco.Core/Events/ImportEventArgs.cs +++ b/src/Umbraco.Core/Events/ImportEventArgs.cs @@ -4,7 +4,7 @@ using System.Xml.Linq; namespace Umbraco.Core.Events { - public class ImportEventArgs : CancellableObjectEventArgs>, IEquatable> + public class ImportEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> { /// /// Constructor accepting an XElement with the xml being imported diff --git a/src/Umbraco.Core/Events/ImportPackageEventArgs.cs b/src/Umbraco.Core/Events/ImportPackageEventArgs.cs index 06ce0c60e2..2fb0870b16 100644 --- a/src/Umbraco.Core/Events/ImportPackageEventArgs.cs +++ b/src/Umbraco.Core/Events/ImportPackageEventArgs.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Events { - internal class ImportPackageEventArgs : CancellableObjectEventArgs>, IEquatable> + internal class ImportPackageEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> { private readonly MetaData _packageMetaData; @@ -32,7 +32,8 @@ namespace Umbraco.Core.Events public bool Equals(ImportPackageEventArgs other) { if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; + if (ReferenceEquals(this, other)) return true; + //TODO: MetaData for package metadata has no equality operators :/ return base.Equals(other) && _packageMetaData.Equals(other._packageMetaData); } diff --git a/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs b/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs index 4916fd13fd..8ec965c29c 100644 --- a/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs +++ b/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs @@ -5,8 +5,10 @@ using System.Linq; namespace Umbraco.Core.Events { /// - /// This event manager supports event cancellation and will raise the events as soon as they are tracked, it does not store tracked events + /// An IEventDispatcher that immediately raise all events. /// + /// This means that events will be raised during the scope transaction, + /// whatever happens, and the transaction could roll back in the end. internal class PassThroughEventDispatcher : IEventDispatcher { public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null) diff --git a/src/Umbraco.Core/Events/PublishEventArgs.cs b/src/Umbraco.Core/Events/PublishEventArgs.cs index 1aa7c2308c..10bf94146c 100644 --- a/src/Umbraco.Core/Events/PublishEventArgs.cs +++ b/src/Umbraco.Core/Events/PublishEventArgs.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Umbraco.Core.Events { - public class PublishEventArgs : CancellableObjectEventArgs>, IEquatable> + public class PublishEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> { /// /// Constructor accepting multiple entities that are used in the publish operation diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs index 238c9568eb..f7a186502b 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs @@ -4,11 +4,9 @@ using Umbraco.Core.IO; namespace Umbraco.Core.Events { /// - /// This event manager is created for each scope and is aware of if it is nested in an outer scope + /// An IEventDispatcher that queues events, and raise them when the scope + /// exits and has been completed. /// - /// - /// The outer scope is the only scope that can raise events, the inner scope's will defer to the outer scope - /// internal class QueuingEventDispatcher : QueuingEventDispatcherBase { public QueuingEventDispatcher() diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs b/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs index d3f804a50d..4ccbc3719c 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs @@ -1,11 +1,23 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Plugins; namespace Umbraco.Core.Events { + /// + /// An IEventDispatcher that queues events. + /// + /// + /// Can raise, or ignore, cancelable events, depending on option. + /// Implementations must override ScopeExitCompleted to define what + /// to do with the events when the scope exits and has been completed. + /// If the scope exits without being completed, events are ignored. + /// public abstract class QueuingEventDispatcherBase : IEventDispatcher { + //events will be enlisted in the order they are raised private List _events; private readonly bool _raiseCancelable; @@ -68,26 +80,256 @@ namespace Umbraco.Core.Events switch (filter) { case EventDefinitionFilter.All: - return _events; + return FilterSupersededAndUpdateToLatestEntity(_events); case EventDefinitionFilter.FirstIn: var l1 = new OrderedHashSet(); foreach (var e in _events) - { l1.Add(e); - } - return l1; + return FilterSupersededAndUpdateToLatestEntity(l1); case EventDefinitionFilter.LastIn: var l2 = new OrderedHashSet(keepOldest: false); foreach (var e in _events) - { l2.Add(e); - } - return l2; + return FilterSupersededAndUpdateToLatestEntity(l2); default: throw new ArgumentOutOfRangeException(nameof(filter), filter, null); } } + private class EventDefinitionTypeData + { + public IEventDefinition EventDefinition { get; set; } + public Type EventArgType { get; set; } + public SupersedeEventAttribute[] SupersedeAttributes { get; set; } + } + + /// + /// This will iterate over the events (latest first) and filter out any events or entities in event args that are included + /// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want + /// to raise the Saved event (well actually we just don't want to include it in the args for that saved event) + /// + /// + /// + private static IEnumerable FilterSupersededAndUpdateToLatestEntity(IReadOnlyList events) + { + //used to keep the 'latest' entity and associated event definition data + var allEntities = new List>(); + + //tracks all CancellableObjectEventArgs instances in the events which is the only type of args we can work with + var cancelableArgs = new List(); + + var result = new List(); + + //This will eagerly load all of the event arg types and their attributes so we don't have to continuously look this data up + var allArgTypesWithAttributes = events.Select(x => x.Args.GetType()) + .Distinct() + .ToDictionary(x => x, x => x.GetCustomAttributes(false).ToArray()); + + //Iterate all events and collect the actual entities in them and relates them to their corresponding EventDefinitionTypeData + //we'll process the list in reverse because events are added in the order they are raised and we want to filter out + //any entities from event args that are not longer relevant + //(i.e. if an item is Deleted after it's Saved, we won't include the item in the Saved args) + for (var index = events.Count - 1; index >= 0; index--) + { + var eventDefinition = events[index]; + + var argType = eventDefinition.Args.GetType(); + var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()]; + + var meta = new EventDefinitionTypeData + { + EventDefinition = eventDefinition, + EventArgType = argType, + SupersedeAttributes = attributes + }; + + var args = eventDefinition.Args as CancellableObjectEventArgs; + if (args != null) + { + var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject); + + if (list == null) + { + //extract the event object + var obj = args.EventObject as IEntity; + if (obj != null) + { + //Now check if this entity already exists in other event args that supersede this current event arg type + if (IsFiltered(obj, meta, allEntities) == false) + { + //if it's not filtered we can adde these args to the response + cancelableArgs.Add(args); + result.Add(eventDefinition); + //track the entity + allEntities.Add(Tuple.Create(obj, meta)); + } + } + else + { + //Can't retrieve the entity so cant' filter or inspect, just add to the output + result.Add(eventDefinition); + } + } + else + { + var toRemove = new List(); + foreach (var entity in list) + { + //extract the event object + var obj = entity as IEntity; + if (obj != null) + { + //Now check if this entity already exists in other event args that supersede this current event arg type + if (IsFiltered(obj, meta, allEntities)) + { + //track it to be removed + toRemove.Add(obj); + } + else + { + //track the entity, it's not filtered + allEntities.Add(Tuple.Create(obj, meta)); + } + } + else + { + //we don't need to do anything here, we can't cast to IEntity so we cannot filter, so it will just remain in the list + } + } + + //remove anything that has been filtered + foreach (var entity in toRemove) + { + list.Remove(entity); + } + + //track the event and include in the response if there's still entities remaining in the list + if (list.Count > 0) + { + if (toRemove.Count > 0) + { + //re-assign if the items have changed + args.EventObject = list; + } + cancelableArgs.Add(args); + result.Add(eventDefinition); + } + } + } + else + { + //it's not a cancelable event arg so we just include it in the result + result.Add(eventDefinition); + } + } + + //Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args + UpdateToLatestEntities(allEntities, cancelableArgs); + + //we need to reverse the result since we've been adding by latest added events first! + result.Reverse(); + + return result; + } + + private static void UpdateToLatestEntities(IEnumerable> allEntities, IEnumerable cancelableArgs) + { + //Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args + + var latestEntities = new OrderedHashSet(keepOldest: true); + foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate)) + { + latestEntities.Add(entity.Item1); + } + + foreach (var args in cancelableArgs) + { + var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject); + if (list == null) + { + //try to find the args entity in the latest entity - based on the equality operators, this will + //match by Id since that is the default equality checker for IEntity. If one is found, than it is + //the most recent entity instance so update the args with that instance so we don't emit a stale instance. + var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, args.EventObject)); + if (foundEntity != null) + { + args.EventObject = foundEntity; + } + } + else + { + var updated = false; + + for (int i = 0; i < list.Count; i++) + { + //try to find the args entity in the latest entity - based on the equality operators, this will + //match by Id since that is the default equality checker for IEntity. If one is found, than it is + //the most recent entity instance so update the args with that instance so we don't emit a stale instance. + var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, list[i])); + if (foundEntity != null) + { + list[i] = foundEntity; + updated = true; + } + } + + if (updated) + { + args.EventObject = list; + } + } + } + } + + /// + /// This will check against all of the processed entity/events (allEntities) to see if this entity already exists in + /// event args that supersede the event args being passed in and if so returns true. + /// + /// + /// + /// + /// + private static bool IsFiltered( + IEntity entity, + EventDefinitionTypeData eventDef, + List> allEntities) + { + var argType = eventDef.EventDefinition.Args.GetType(); + + //check if the entity is found in any processed event data that could possible supersede this one + var foundByEntity = allEntities + .Where(x => x.Item2.SupersedeAttributes.Length > 0 + //if it's the same arg type than it cannot supersede + && x.Item2.EventArgType != argType + && Equals(x.Item1, entity)) + .ToArray(); + + //no args have been processed with this entity so it should not be filtered + if (foundByEntity.Length == 0) + return false; + + if (argType.IsGenericType) + { + var supercededBy = foundByEntity + .FirstOrDefault(x => + x.Item2.SupersedeAttributes.Any(y => + //if the attribute type is a generic type def then compare with the generic type def of the event arg + (y.SupersededEventArgsType.IsGenericTypeDefinition && y.SupersededEventArgsType == argType.GetGenericTypeDefinition()) + //if the attribute type is not a generic type def then compare with the normal type of the event arg + || (y.SupersededEventArgsType.IsGenericTypeDefinition == false && y.SupersededEventArgsType == argType))); + return supercededBy != null; + } + else + { + var supercededBy = foundByEntity + .FirstOrDefault(x => + x.Item2.SupersedeAttributes.Any(y => + //since the event arg type is not a generic type, then we just compare type 1:1 + y.SupersededEventArgsType == argType)); + return supercededBy != null; + } + } + public void ScopeExit(bool completed) { if (_events == null) return; diff --git a/src/Umbraco.Core/Events/SaveEventArgs.cs b/src/Umbraco.Core/Events/SaveEventArgs.cs index dafd326e1c..cd19038d8e 100644 --- a/src/Umbraco.Core/Events/SaveEventArgs.cs +++ b/src/Umbraco.Core/Events/SaveEventArgs.cs @@ -1,8 +1,9 @@ using System.Collections.Generic; +using System.Linq; namespace Umbraco.Core.Events { - public class SaveEventArgs : CancellableObjectEventArgs> + public class SaveEventArgs : CancellableEnumerableObjectEventArgs { /// /// Constructor accepting multiple entities that are used in the saving operation diff --git a/src/Umbraco.Core/Events/SupersedeEventAttribute.cs b/src/Umbraco.Core/Events/SupersedeEventAttribute.cs new file mode 100644 index 0000000000..c7a14ea158 --- /dev/null +++ b/src/Umbraco.Core/Events/SupersedeEventAttribute.cs @@ -0,0 +1,20 @@ +using System; + +namespace Umbraco.Core.Events +{ + /// + /// This is used to know if the event arg attributed should supersede another event arg type when + /// tracking events for the same entity. If one event args supercedes another then the event args that have been superseded + /// will mean that the event will not be dispatched or the args will be filtered to exclude the entity. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + internal class SupersedeEventAttribute : Attribute + { + public Type SupersededEventArgsType { get; private set; } + + public SupersedeEventAttribute(Type supersededEventArgsType) + { + SupersededEventArgsType = supersededEventArgsType; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Exceptions/ConnectionException.cs b/src/Umbraco.Core/Exceptions/ConnectionException.cs new file mode 100644 index 0000000000..3535dd52bf --- /dev/null +++ b/src/Umbraco.Core/Exceptions/ConnectionException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Umbraco.Core.Exceptions +{ + internal class ConnectionException : Exception + { + public ConnectionException(string message, Exception innerException) : base(message, innerException) + { + + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Exceptions/DataOperationException.cs b/src/Umbraco.Core/Exceptions/DataOperationException.cs index 9a66e6a5be..60a3ccd4eb 100644 --- a/src/Umbraco.Core/Exceptions/DataOperationException.cs +++ b/src/Umbraco.Core/Exceptions/DataOperationException.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.Exceptions public T Operation { get; private set; } public DataOperationException(T operation, string message) - :base(message) + : base(message) { Operation = operation; } diff --git a/src/Umbraco.Core/HashCodeCombiner.cs b/src/Umbraco.Core/HashCodeCombiner.cs index b97a3cfacf..6d65ab3704 100644 --- a/src/Umbraco.Core/HashCodeCombiner.cs +++ b/src/Umbraco.Core/HashCodeCombiner.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; -using System.Text; namespace Umbraco.Core { @@ -55,14 +52,14 @@ namespace Umbraco.Core AddCaseInsensitiveString(f.FullName); AddDateTime(f.CreationTimeUtc); AddDateTime(f.LastWriteTimeUtc); - - //check if it is a file or folder + + //check if it is a file or folder var fileInfo = f as FileInfo; if (fileInfo != null) { AddInt(fileInfo.Length.GetHashCode()); } - + var dirInfo = f as DirectoryInfo; if (dirInfo != null) { @@ -79,12 +76,12 @@ namespace Umbraco.Core internal void AddFile(FileInfo f) { - AddFileSystemItem(f); + AddFileSystemItem(f); } internal void AddFolder(DirectoryInfo d) { - AddFileSystemItem(d); + AddFileSystemItem(d); } /// diff --git a/src/Umbraco.Core/HashCodeHelper.cs b/src/Umbraco.Core/HashCodeHelper.cs new file mode 100644 index 0000000000..f0f281056d --- /dev/null +++ b/src/Umbraco.Core/HashCodeHelper.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; + +namespace Umbraco.Core +{ + /// + /// Borrowed from http://stackoverflow.com/a/2575444/694494 + /// + internal static class HashCodeHelper + { + public static int GetHashCode(T1 arg1, T2 arg2) + { + unchecked + { + return 31 * arg1.GetHashCode() + arg2.GetHashCode(); + } + } + + public static int GetHashCode(T1 arg1, T2 arg2, T3 arg3) + { + unchecked + { + int hash = arg1.GetHashCode(); + hash = 31 * hash + arg2.GetHashCode(); + return 31 * hash + arg3.GetHashCode(); + } + } + + public static int GetHashCode(T1 arg1, T2 arg2, T3 arg3, + T4 arg4) + { + unchecked + { + int hash = arg1.GetHashCode(); + hash = 31 * hash + arg2.GetHashCode(); + hash = 31 * hash + arg3.GetHashCode(); + return 31 * hash + arg4.GetHashCode(); + } + } + + public static int GetHashCode(T[] list) + { + unchecked + { + int hash = 0; + foreach (var item in list) + { + if (item == null) continue; + hash = 31 * hash + item.GetHashCode(); + } + return hash; + } + } + + public static int GetHashCode(IEnumerable list) + { + unchecked + { + int hash = 0; + foreach (var item in list) + { + if (item == null) continue; + hash = 31 * hash + item.GetHashCode(); + } + return hash; + } + } + + /// + /// Gets a hashcode for a collection for that the order of items + /// does not matter. + /// So {1, 2, 3} and {3, 2, 1} will get same hash code. + /// + public static int GetHashCodeForOrderNoMatterCollection( + IEnumerable list) + { + unchecked + { + int hash = 0; + int count = 0; + foreach (var item in list) + { + if (item == null) continue; + hash += item.GetHashCode(); + count++; + } + return 31 * hash + count.GetHashCode(); + } + } + + /// + /// Alternative way to get a hashcode is to use a fluent + /// interface like this:
+ /// return 0.CombineHashCode(field1).CombineHashCode(field2). + /// CombineHashCode(field3); + ///
+ public static int CombineHashCode(this int hashCode, T arg) + { + unchecked + { + return 31 * hashCode + arg.GetHashCode(); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 591626e55b..5df4771efe 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -177,7 +177,7 @@ namespace Umbraco.Core.IO } var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories - ? Path.Combine(folder, filename) + ? Path.Combine(folder, filename).Replace('\\', '/') : folder + "-" + filename; return filepath; diff --git a/src/Umbraco.Core/IO/ShadowWrapper.cs b/src/Umbraco.Core/IO/ShadowWrapper.cs index b53355211f..be540f5099 100644 --- a/src/Umbraco.Core/IO/ShadowWrapper.cs +++ b/src/Umbraco.Core/IO/ShadowWrapper.cs @@ -52,9 +52,20 @@ namespace Umbraco.Core.IO try { Directory.Delete(dir, true); - dir = dir.Substring(0, dir.Length - _shadowPath.Length - 1); - if (Directory.EnumerateFileSystemEntries(dir).Any() == false) - Directory.Delete(dir, true); + + // shadowPath make be path/to/dir, remove each + dir = dir.Replace("/", "\\"); + var min = IOHelper.MapPath("~/App_Data/TEMP/ShadowFs").Length; + var pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase); + while (pos > min) + { + dir = dir.Substring(0, pos); + if (Directory.EnumerateFileSystemEntries(dir).Any() == false) + Directory.Delete(dir, true); + else + break; + pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase); + } } catch { diff --git a/src/Umbraco.Core/Models/ContentXmlEntity.cs b/src/Umbraco.Core/Models/ContentXmlEntity.cs index 0450fdc72e..930ea47900 100644 --- a/src/Umbraco.Core/Models/ContentXmlEntity.cs +++ b/src/Umbraco.Core/Models/ContentXmlEntity.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Models /// Used in content/media/member repositories in order to add this type of entity to the persisted collection to be saved /// in a single transaction during saving an entity ///
- internal class ContentXmlEntity : IAggregateRoot + internal class ContentXmlEntity : IAggregateRoot // fixme kill? where TContent : IContentBase { private readonly Func _xml; @@ -42,6 +42,7 @@ namespace Umbraco.Core.Models public Guid Key { get; set; } public DateTime CreateDate { get; set; } public DateTime UpdateDate { get; set; } + public DateTime? DeletedDate { get; set; } /// /// Special case, always return false, this will cause the repositories managing diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index d605759ed1..048b37ea2a 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -1,10 +1,7 @@ using System; using System.Diagnostics; -using System.IO; using System.Reflection; using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; -using System.Text; namespace Umbraco.Core.Models.EntityBase { @@ -13,8 +10,8 @@ namespace Umbraco.Core.Models.EntityBase /// [Serializable] [DataContract(IsReference = true)] - [DebuggerDisplay("Id: {Id}")] - public abstract class Entity : TracksChangesEntityBase, IEntity, IRememberBeingDirty, ICanBeDirty + [DebuggerDisplay("Id: {" + nameof(Id) + "}")] + public abstract class Entity : TracksChangesEntityBase, IEntity //, IRememberBeingDirty, ICanBeDirty { private bool _hasIdentity; private int _id; @@ -25,6 +22,7 @@ namespace Umbraco.Core.Models.EntityBase private static readonly Lazy Ps = new Lazy(); + // ReSharper disable once ClassNeverInstantiated.Local private class PropertySelectors { public readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo(x => x.Id); @@ -41,7 +39,7 @@ namespace Umbraco.Core.Models.EntityBase [DataMember] public int Id { - get { return _id; } + get => _id; set { SetPropertyValueAndDetectChanges(value, ref _id, Ps.Value.IdSelector); @@ -64,7 +62,7 @@ namespace Umbraco.Core.Models.EntityBase _key = Guid.NewGuid(); return _key; } - set { SetPropertyValueAndDetectChanges(value, ref _key, Ps.Value.KeySelector); } + set => SetPropertyValueAndDetectChanges(value, ref _key, Ps.Value.KeySelector); } /// @@ -73,8 +71,8 @@ namespace Umbraco.Core.Models.EntityBase [DataMember] public DateTime CreateDate { - get { return _createDate; } - set { SetPropertyValueAndDetectChanges(value, ref _createDate, Ps.Value.CreateDateSelector); } + get => _createDate; + set => SetPropertyValueAndDetectChanges(value, ref _createDate, Ps.Value.CreateDateSelector); } /// @@ -87,8 +85,8 @@ namespace Umbraco.Core.Models.EntityBase [Obsolete("Anytime there's a cancellable method it needs to return an Attempt so we know the outcome instead of this hack, not all services have been updated to use this though yet.")] internal bool WasCancelled { - get { return _wasCancelled; } - set { SetPropertyValueAndDetectChanges(value, ref _wasCancelled, Ps.Value.WasCancelledSelector); } + get => _wasCancelled; + set => SetPropertyValueAndDetectChanges(value, ref _wasCancelled, Ps.Value.WasCancelledSelector); } /// @@ -97,10 +95,13 @@ namespace Umbraco.Core.Models.EntityBase [DataMember] public DateTime UpdateDate { - get { return _updateDate; } - set { SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); } + get => _updateDate; + set => SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); } + [IgnoreDataMember] + public DateTime? DeletedDate { get; set; } + internal virtual void ResetIdentity() { _hasIdentity = false; @@ -134,32 +135,19 @@ namespace Umbraco.Core.Models.EntityBase [DataMember] public virtual bool HasIdentity { - get - { - return _hasIdentity; - } - protected set { SetPropertyValueAndDetectChanges(value, ref _hasIdentity, Ps.Value.HasIdentitySelector); } + get => _hasIdentity; + protected set => SetPropertyValueAndDetectChanges(value, ref _hasIdentity, Ps.Value.HasIdentitySelector); } //TODO: Make this NOT virtual or even exist really! public virtual bool SameIdentityAs(IEntity other) { - if (ReferenceEquals(null, other)) - return false; - if (ReferenceEquals(this, other)) - return true; - - return SameIdentityAs(other as Entity); + return other != null && (ReferenceEquals(this, other) || SameIdentityAs(other as Entity)); } public virtual bool Equals(Entity other) { - if (ReferenceEquals(null, other)) - return false; - if (ReferenceEquals(this, other)) - return true; - - return SameIdentityAs(other); + return other != null && (ReferenceEquals(this, other) || SameIdentityAs(other)); } //TODO: Make this NOT virtual or even exist really! @@ -185,12 +173,7 @@ namespace Umbraco.Core.Models.EntityBase public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) - return false; - if (ReferenceEquals(this, obj)) - return true; - - return SameIdentityAs(obj as IEntity); + return obj != null && (ReferenceEquals(this, obj) || SameIdentityAs(obj as IEntity)); } public override int GetHashCode() @@ -208,7 +191,7 @@ namespace Umbraco.Core.Models.EntityBase { //Memberwise clone on Entity will work since it doesn't have any deep elements // for any sub class this will work for standard properties as well that aren't complex object's themselves. - var ignored = this.Key; // ensure that 'this' has a key, before cloning + var unused = Key; // ensure that 'this' has a key, before cloning var clone = (Entity)MemberwiseClone(); //ensure the clone has it's own dictionaries clone.ResetChangeTrackingCollections(); diff --git a/src/Umbraco.Core/Models/EntityBase/IAggregateRoot.cs b/src/Umbraco.Core/Models/EntityBase/IAggregateRoot.cs index 4298dd9cf4..ad81b67205 100644 --- a/src/Umbraco.Core/Models/EntityBase/IAggregateRoot.cs +++ b/src/Umbraco.Core/Models/EntityBase/IAggregateRoot.cs @@ -3,8 +3,6 @@ /// /// Marker interface for aggregate roots /// - public interface IAggregateRoot : IEntity - { - - } + public interface IAggregateRoot : IDeletableEntity + { } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/EntityBase/IDeletableEntity.cs b/src/Umbraco.Core/Models/EntityBase/IDeletableEntity.cs new file mode 100644 index 0000000000..42f91b6a6c --- /dev/null +++ b/src/Umbraco.Core/Models/EntityBase/IDeletableEntity.cs @@ -0,0 +1,11 @@ +using System; +using System.Runtime.Serialization; + +namespace Umbraco.Core.Models.EntityBase +{ + public interface IDeletableEntity : IEntity + { + [DataMember] + DateTime? DeletedDate { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/IPartialView.cs b/src/Umbraco.Core/Models/IPartialView.cs index 01127ce22a..40a760427a 100644 --- a/src/Umbraco.Core/Models/IPartialView.cs +++ b/src/Umbraco.Core/Models/IPartialView.cs @@ -2,6 +2,6 @@ { public interface IPartialView : IFile { - + PartialViewType ViewType { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PartialView.cs b/src/Umbraco.Core/Models/PartialView.cs index 75914820f0..3c7a3ee908 100644 --- a/src/Umbraco.Core/Models/PartialView.cs +++ b/src/Umbraco.Core/Models/PartialView.cs @@ -1,10 +1,8 @@ using System; using System.Runtime.Serialization; -using Umbraco.Core.Services; namespace Umbraco.Core.Models { - /// /// Represents a Partial View file /// @@ -12,14 +10,21 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class PartialView : File, IPartialView { + [Obsolete("Use the ctor that explicitely sets the view type.")] public PartialView(string path) - : this(path, null) + : this(PartialViewType.PartialView, path, null) { } - internal PartialView(string path, Func getFileContent) + public PartialView(PartialViewType viewType, string path) + : this(viewType, path, null) + { } + + internal PartialView(PartialViewType viewType, string path, Func getFileContent) : base(path, getFileContent) - { } + { + ViewType = viewType; + } - internal PartialViewType ViewType { get; set; } + public PartialViewType ViewType { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PartialViewType.cs b/src/Umbraco.Core/Models/PartialViewType.cs index 2b45448271..6204b6e165 100644 --- a/src/Umbraco.Core/Models/PartialViewType.cs +++ b/src/Umbraco.Core/Models/PartialViewType.cs @@ -1,6 +1,6 @@ namespace Umbraco.Core.Models { - internal enum PartialViewType : byte + public enum PartialViewType : byte { Unknown = 0, // default PartialView = 1, diff --git a/src/Umbraco.Core/OrderedHashSet.cs b/src/Umbraco.Core/OrderedHashSet.cs index 2fd545c915..801f1a9a41 100644 --- a/src/Umbraco.Core/OrderedHashSet.cs +++ b/src/Umbraco.Core/OrderedHashSet.cs @@ -11,7 +11,7 @@ namespace Umbraco.Core { private readonly bool _keepOldest; - public OrderedHashSet(bool keepOldest = true) + public OrderedHashSet(bool keepOldest = true) { _keepOldest = keepOldest; } diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs index 4ea8696316..840bb95bda 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationBase.cs @@ -1,4 +1,5 @@ -using NPoco; +using System; +using NPoco; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Migrations.Syntax.Alter; using Umbraco.Core.Persistence.Migrations.Syntax.Create; @@ -27,8 +28,15 @@ namespace Umbraco.Core.Persistence.Migrations Context = context; } - public abstract void Up(); - public abstract void Down(); + public virtual void Up() + { + throw new NotSupportedException("This migration does not implement the \"up\" operation."); + } + + public virtual void Down() + { + throw new NotSupportedException("This migration does not implement the \"down\" operation."); + } public IAlterSyntaxBuilder Alter => new AlterSyntaxBuilder(Context); diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs index b4890e72ce..4cbb628477 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/AlterSyntaxBuilder.cs @@ -1,4 +1,5 @@ -using NPoco; +using System; +using NPoco; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table; @@ -23,6 +24,15 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter return new AlterTableBuilder(_context, _supportedDatabaseTypes, expression); } + /// + /// The problem with this is that only under particular circumstances is the expression added to the context + /// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore + /// the statement won't even execute whereas using the IAlterTableSyntax to modify a column is guaranteed to add + /// the expression to the context. + /// + /// + /// + [Obsolete("Use the IAlterTableSyntax to modify a column instead, this will be removed in future versions")] public IAlterColumnSyntax Column(string columnName) { var expression = new AlterColumnExpression(_context, _supportedDatabaseTypes) {Column = {Name = columnName}}; diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs index 479c2eadce..77db6b8cde 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs @@ -1,11 +1,22 @@ -using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; +using System; +using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table; namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter { public interface IAlterSyntaxBuilder : IFluentSyntax { - IAlterTableSyntax Table(string tableName); + IAlterTableSyntax Table(string tableName); + + /// + /// The problem with this is that only under particular circumstances is the expression added to the context + /// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore + /// the statement won't even execute whereas using the IAlterTableSyntax to modify a column is guaranteed to add + /// the expression to the context. + /// + /// + /// + [Obsolete("Use the IAlterTableSyntax to modify a column instead, this will be removed in future versions")] IAlterColumnSyntax Column(string columnName); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs index 979faf27f2..4df4c198c7 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] + [Migration("7.6.0", 3, Constants.System.UmbracoMigrationName)] public class AddIndexToCmsMemberLoginName : MigrationBase { public AddIndexToCmsMemberLoginName(IMigrationContext context) @@ -13,17 +13,40 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero public override void Up() { - var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); - - //make sure it doesn't already exist - if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false) + Execute.Code(database => { - Create.Index("IX_cmsMember_LoginName").OnTable("cmsMember") - .OnColumn("LoginName") - .Ascending() - .WithOptions() - .NonClustered(); - } + //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long + //http://issues.umbraco.org/issue/U4-9758 + + var colLen = SqlSyntax is MySqlSyntaxProvider + ? database.ExecuteScalar("select max(LENGTH(LoginName)) from cmsMember") + : database.ExecuteScalar("select max(datalength(LoginName)) from cmsMember"); + + if (colLen < 900 == false && colLen != null) + { + return null; + } + + var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); + + //make sure it doesn't already exist + if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false) + { + var local = Context.GetLocalMigration(); + + //we can apply the index + local.Create.Index("IX_cmsMember_LoginName").OnTable("cmsMember") + .OnColumn("LoginName") + .Ascending() + .WithOptions() + .NonClustered(); + + return local.GetSql(); + } + + return null; + + }); } public override void Down() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs new file mode 100644 index 0000000000..3c76fd11cf --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs @@ -0,0 +1,49 @@ +using System; +using System.Linq; +using Umbraco.Core.Exceptions; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero +{ + [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] + public class NormalizeTemplateGuids : MigrationBase + { + public NormalizeTemplateGuids(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + Execute.Code(UpdateTemplateGuids); + } + + private static string UpdateTemplateGuids(IUmbracoDatabase database) + { + // we need this migration because ppl running pre-7.6 on Cloud and Courier have templates in different + // environments having different GUIDs (Courier does not sync template GUIDs) and we need to normalize + // these GUIDs so templates with the same alias on different environments have the same GUID. + // however, if already running a prerelease version of 7.6, we do NOT want to normalize the GUIDs as quite + // probably, we are already running Deploy and the GUIDs are OK. assuming noone is running a prerelease + // of 7.6 on Courier. + // so... testing if we already have a 7.6.0 version installed. not pretty but...? + // + var version = database.FirstOrDefault("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoMigrationName }); + if (version != null && version.StartsWith("7.6.0")) return string.Empty; + + var updates = database.Query(@"SELECT umbracoNode.id, cmsTemplate.alias FROM umbracoNode +JOIN cmsTemplate ON umbracoNode.id=cmsTemplate.nodeId +WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateTypeGuid}) + .Select(template => Tuple.Create((int) template.id, ("template____" + (string) template.alias).ToGuid())) + .ToList(); + + foreach (var update in updates) + database.Execute("UPDATE umbracoNode set uniqueId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 }); + + return string.Empty; + } + + public override void Down() + { + throw new WontImplementException(); + } + } +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs new file mode 100644 index 0000000000..bbea258c3b --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs @@ -0,0 +1,48 @@ +using System.Linq; +using Umbraco.Core.Exceptions; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero +{ + [Migration("7.6.0", 2, Constants.System.UmbracoMigrationName)] + public class ReduceLoginNameColumnsSize : MigrationBase + { + public ReduceLoginNameColumnsSize(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long + //http://issues.umbraco.org/issue/U4-9758 + + Execute.Code(database => + { + var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database); + + var colLen = (SqlSyntax is MySqlSyntaxProvider) + ? database.ExecuteScalar("select max(LENGTH(LoginName)) from cmsMember") + : database.ExecuteScalar("select max(datalength(LoginName)) from cmsMember"); + + if (colLen < 900 == false) return null; + + var local = Context.GetLocalMigration(); + + //if it exists we need to drop it first + if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName"))) + { + local.Delete.Index("IX_cmsMember_LoginName").OnTable("cmsMember"); + } + + //we can apply the col length change + local.Alter.Table("cmsMember") + .AlterColumn("LoginName") + .AsString(225) + .NotNullable(); + + return local.GetSql(); + }); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs index 162c4f618e..340b5c06da 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe }).ToArray(); //must be non-nullable - Alter.Column("uniqueID").OnTable("umbracoNode").AsGuid().NotNullable(); + Alter.Table("umbracoNode").AlterColumn("uniqueID").AsGuid().NotNullable(); //make sure it already exists if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID"))) diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index 65708ef299..b3da57b98b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -285,6 +285,8 @@ AND umbracoNode.id <> @id", //Delete (base) node data Database.Delete("WHERE uniqueID = @Id", new { Id = entity.Key }); + + entity.DeletedDate = DateTime.Now; } #endregion @@ -551,6 +553,8 @@ AND umbracoNode.id <> @id", protected override void PersistDeletedItem(PreValueEntity entity) { Database.Execute("DELETE FROM cmsDataTypePreValues WHERE id=@Id", new { Id = entity.Id }); + + entity.DeletedDate = DateTime.Now; } protected override void PersistNewItem(PreValueEntity entity) diff --git a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs index 129c9922eb..ddc42b69f3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs @@ -195,6 +195,8 @@ namespace Umbraco.Core.Persistence.Repositories //Clear the cache entries that exist by uniqueid/item key IsolatedCache.ClearCacheItem(GetCacheIdKey(entity.ItemKey)); IsolatedCache.ClearCacheItem(GetCacheIdKey(entity.Key)); + + entity.DeletedDate = DateTime.Now; } private void RecursiveDelete(Guid parentId) diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs index 9cad3200f8..fe26b23143 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs @@ -157,6 +157,8 @@ namespace Umbraco.Core.Persistence.Repositories // delete Database.Delete(nodeDto); + + entity.DeletedDate = DateTime.Now; } protected override void PersistNewItem(EntityContainer entity) diff --git a/src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs index c3622d6532..7b9be2a3c9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/NPocoRepositoryBase.cs @@ -89,6 +89,7 @@ namespace Umbraco.Core.Persistence.Repositories { Database.Execute(delete, new { Id = GetEntityId(entity) }); } + entity.DeletedDate = DateTime.Now; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs index 366a4265ea..9d3acb6d02 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PartialViewRepository.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories var updated = FileSystem.GetLastModified(path).UtcDateTime; //var content = GetFileContent(path); - var view = new PartialView(path, file => GetFileContent(file.OriginalPath)) + var view = new PartialView(ViewType, path, file => GetFileContent(file.OriginalPath)) { //id can be the hash Id = path.GetHashCode(), @@ -38,8 +38,7 @@ namespace Umbraco.Core.Persistence.Repositories //Content = content, CreateDate = created, UpdateDate = updated, - VirtualPath = FileSystem.GetUrl(id), - ViewType = ViewType + VirtualPath = FileSystem.GetUrl(id) }; //on initial construction we don't want to have dirty properties tracked diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs index 86b8f39a5c..687839c943 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs @@ -120,6 +120,11 @@ namespace Umbraco.Core.Persistence.Repositories Database.Update(dto); + foreach (var removedRule in entity.RemovedRules) + { + Database.Delete("WHERE id=@Id", new { Id = removedRule }); + } + foreach (var rule in entity.Rules) { if (rule.HasIdentity) @@ -145,10 +150,6 @@ namespace Umbraco.Core.Persistence.Repositories rule.Id = rule.Key.GetHashCode(); } } - foreach (var removedRule in entity.RemovedRules) - { - Database.Delete("WHERE id=@Id", new {Id = removedRule}); - } entity.ResetDirtyProperties(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index afbc57c3b2..0acecc4d42 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -318,6 +318,8 @@ namespace Umbraco.Core.Persistence.Repositories var masterpageName = string.Concat(entity.Alias, ".master"); _masterpagesFileSystem.DeleteFile(masterpageName); } + + entity.DeletedDate = DateTime.Now; } #endregion diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs index de737d70c3..5c268175a2 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Data; using NPoco; using Umbraco.Core.Events; -using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; diff --git a/src/Umbraco.Core/Plugins/TypeHelper.cs b/src/Umbraco.Core/Plugins/TypeHelper.cs index fa7e48109b..a8450af1c2 100644 --- a/src/Umbraco.Core/Plugins/TypeHelper.cs +++ b/src/Umbraco.Core/Plugins/TypeHelper.cs @@ -1,6 +1,8 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Reflection; @@ -19,6 +21,47 @@ namespace Umbraco.Core.Plugins private static readonly Assembly[] EmptyAssemblies = new Assembly[0]; + /// + /// Based on a type we'll check if it is IEnumerable{T} (or similar) and if so we'll return a List{T}, this will also deal with array types and return List{T} for those too. + /// If it cannot be done, null is returned. + /// + /// + /// + // fixme wtf is this and do we need it in v8? + internal static IList CreateGenericEnumerableFromObject(object obj) + { + var type = obj.GetType(); + + if (type.IsGenericType) + { + var genericTypeDef = type.GetGenericTypeDefinition(); + + if (genericTypeDef == typeof(IEnumerable<>) + || genericTypeDef == typeof(ICollection<>) + || genericTypeDef == typeof(Collection<>) + || genericTypeDef == typeof(IList<>) + || genericTypeDef == typeof(List<>) + //this will occur when Linq is used and we get the odd WhereIterator or DistinctIterators since those are special iterator types + || obj is IEnumerable) + { + //if it is a IEnumerable<>, IList or ICollection<> we'll use a List<> + var genericType = typeof(List<>).MakeGenericType(type.GetGenericArguments()); + //pass in obj to fill the list + return (IList)Activator.CreateInstance(genericType, obj); + } + } + + if (type.IsArray) + { + //if its an array, we'll use a List<> + var genericType = typeof(List<>).MakeGenericType(type.GetElementType()); + //pass in obj to fill the list + return (IList)Activator.CreateInstance(genericType, obj); + } + + return null; + } + /// /// Checks if the method is actually overriding a base method /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs index 47689b266a..34013e5253 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters public override object ConvertInterToObject(PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview) { - return source.ToString(); + return source?.ToString() ?? string.Empty; } } } diff --git a/src/Umbraco.Core/Scoping/Scope.cs b/src/Umbraco.Core/Scoping/Scope.cs index 321cf6d297..51084f026a 100644 --- a/src/Umbraco.Core/Scoping/Scope.cs +++ b/src/Umbraco.Core/Scoping/Scope.cs @@ -433,6 +433,7 @@ namespace Umbraco.Core.Scoping } finally { + // removes the ambient context (ambient scope already gone) _scopeProvider.SetAmbient(null); } } diff --git a/src/Umbraco.Core/Scoping/ScopeContext.cs b/src/Umbraco.Core/Scoping/ScopeContext.cs index 498285f8b0..6172fb51a3 100644 --- a/src/Umbraco.Core/Scoping/ScopeContext.cs +++ b/src/Umbraco.Core/Scoping/ScopeContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Umbraco.Core.Scoping { @@ -9,11 +10,17 @@ namespace Umbraco.Core.Scoping public class ScopeContext : IInstanceIdentifiable { private Dictionary _enlisted; + private bool _exiting; public void ScopeExit(bool completed) { + if (_enlisted == null) + return; + + _exiting = true; + List exceptions = null; - foreach (var enlisted in Enlisted.Values) + foreach (var enlisted in _enlisted.Values.OrderBy(x => x.Priority)) { try { @@ -26,6 +33,7 @@ namespace Umbraco.Core.Scoping exceptions.Add(e); } } + if (exceptions != null) throw new AggregateException("Exceptions were thrown by listed actions.", exceptions); } @@ -38,73 +46,71 @@ namespace Umbraco.Core.Scoping private interface IEnlistedObject { void Execute(bool completed); + int Priority { get; } } private class EnlistedObject : IEnlistedObject { private readonly Action _action; - public EnlistedObject(T item) - { - Item = item; - } - - public EnlistedObject(T item, Action action) + public EnlistedObject(T item, Action action, int priority) { Item = item; + Priority = priority; _action = action; } public T Item { get; } + public int Priority { get; private set; } + public void Execute(bool completed) { _action(completed, Item); } } - /// + // todo: replace with optional parameters when we can break things public T Enlist(string key, Func creator) { - IEnlistedObject enlisted; - if (Enlisted.TryGetValue(key, out enlisted)) - { - var enlistedAs = enlisted as EnlistedObject; - if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key."); - return enlistedAs.Item; - } - var enlistedOfT = new EnlistedObject(creator()); - Enlisted[key] = enlistedOfT; - return enlistedOfT.Item; + return Enlist(key, creator, null, 100); } - /// + // todo: replace with optional parameters when we can break things public T Enlist(string key, Func creator, Action action) { - IEnlistedObject enlisted; - if (Enlisted.TryGetValue(key, out enlisted)) - { - var enlistedAs = enlisted as EnlistedObject; - if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key."); - return enlistedAs.Item; - } - var enlistedOfT = new EnlistedObject(creator(), action); - Enlisted[key] = enlistedOfT; - return enlistedOfT.Item; + return Enlist(key, creator, action, 100); } - /// + // todo: replace with optional parameters when we can break things public void Enlist(string key, Action action) { + Enlist(key, null, (completed, item) => action(completed), 100); + } + + public void Enlist(string key, Action action, int priority) + { + Enlist(key, null, (completed, item) => action(completed), priority); + } + + public T Enlist(string key, Func creator, Action action, int priority) + { + if (_exiting) + throw new InvalidOperationException("Cannot enlist now, context is exiting."); + + var enlistedObjects = _enlisted ?? (_enlisted = new Dictionary()); + IEnlistedObject enlisted; - if (Enlisted.TryGetValue(key, out enlisted)) + if (enlistedObjects.TryGetValue(key, out enlisted)) { - var enlistedAs = enlisted as EnlistedObject; - if (enlistedAs == null) throw new Exception("An item with a different type has already been enlisted with the same key."); - return; + var enlistedAs = enlisted as EnlistedObject; + if (enlistedAs == null) throw new InvalidOperationException("An item with the key already exists, but with a different type."); + if (enlistedAs.Priority != priority) throw new InvalidOperationException("An item with the key already exits, but with a different priority."); + return enlistedAs.Item; } - var enlistedOfT = new EnlistedObject(null, (completed, item) => action(completed)); + var enlistedOfT = new EnlistedObject(creator == null ? default(T) : creator(), action, priority); Enlisted[key] = enlistedOfT; + return enlistedOfT.Item; } } } diff --git a/src/Umbraco.Core/Security/BackOfficeSignInManager.cs b/src/Umbraco.Core/Security/BackOfficeSignInManager.cs index 71bd2474cd..8f5bdad0f6 100644 --- a/src/Umbraco.Core/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Core/Security/BackOfficeSignInManager.cs @@ -191,6 +191,7 @@ namespace Umbraco.Core.Security //track the last login date user.LastLoginDateUtc = DateTime.UtcNow; + user.AccessFailedCount = 0; await UserManager.UpdateAsync(user); _logger.WriteCore(TraceEventType.Information, 0, diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index d4cae25884..d6a20eaf85 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -126,35 +126,11 @@ namespace Umbraco.Core.Services private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType) { - switch (umbracoObjectType) - { - case UmbracoObjectTypes.Document: - return Constants.ObjectTypes.DocumentGuid; - case UmbracoObjectTypes.MemberType: - return Constants.ObjectTypes.MemberTypeGuid; - case UmbracoObjectTypes.Media: - return Constants.ObjectTypes.MediaGuid; - case UmbracoObjectTypes.Template: - return Constants.ObjectTypes.TemplateTypeGuid; - case UmbracoObjectTypes.MediaType: - return Constants.ObjectTypes.MediaTypeGuid; - case UmbracoObjectTypes.DocumentType: - return Constants.ObjectTypes.DocumentTypeGuid; - case UmbracoObjectTypes.Member: - return Constants.ObjectTypes.MemberGuid; - case UmbracoObjectTypes.DataType: - return Constants.ObjectTypes.DataTypeGuid; - case UmbracoObjectTypes.MemberGroup: - return Constants.ObjectTypes.MemberGroupGuid; - case UmbracoObjectTypes.RecycleBin: - case UmbracoObjectTypes.Stylesheet: - case UmbracoObjectTypes.ContentItem: - case UmbracoObjectTypes.ContentItemType: - case UmbracoObjectTypes.ROOT: - case UmbracoObjectTypes.Unknown: - default: - throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ")."); - } + var guid = umbracoObjectType.GetGuid(); + if (guid == Guid.Empty) + throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ")."); + + return guid; } public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true) diff --git a/src/Umbraco.Core/Services/ExternalLoginService.cs b/src/Umbraco.Core/Services/ExternalLoginService.cs index 29dc030014..b2dea55372 100644 --- a/src/Umbraco.Core/Services/ExternalLoginService.cs +++ b/src/Umbraco.Core/Services/ExternalLoginService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Microsoft.AspNet.Identity; using Umbraco.Core.Events; using Umbraco.Core.Logging; @@ -24,7 +25,9 @@ namespace Umbraco.Core.Services using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { var repo = uow.CreateRepository(); - return repo.GetByQuery(repo.QueryT.Where(x => x.UserId == userId)); + return repo + .GetByQuery(repo.QueryT.Where(x => x.UserId == userId)) + .ToList(); // ToList is important here, must evaluate within uow! } } @@ -39,8 +42,9 @@ namespace Umbraco.Core.Services using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { var repo = uow.CreateRepository(); - return repo.GetByQuery(repo.QueryT - .Where(x => x.ProviderKey == login.ProviderKey && x.LoginProvider == login.LoginProvider)); + return repo + .GetByQuery(repo.QueryT.Where(x => x.ProviderKey == login.ProviderKey && x.LoginProvider == login.LoginProvider)) + .ToList(); // ToList is important here, must evaluate within uow! } } diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index c7e68e6eca..eb0da52b7c 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Xml.Linq; using Umbraco.Core.Models; @@ -186,5 +187,14 @@ namespace Umbraco.Core.Services /// Optional parameter indicating whether or not to raise events /// containing the xml representation of the IMacro object XElement Export(IMacro macro, bool raiseEvents = true); + + /// + /// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file + /// + /// + /// + /// The current user id performing the operation + /// + string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 86ee962dcd..bc971e40ad 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; +using System.Net.Http; using System.Text.RegularExpressions; using System.Web; using System.Web.UI.WebControls; @@ -9,8 +11,10 @@ using System.Xml.Linq; using System.Xml.XPath; using Newtonsoft.Json; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.DI; using Umbraco.Core.Events; +using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -49,7 +53,6 @@ namespace Umbraco.Core.Services private IPackageInstallation _packageInstallation; private readonly IUserService _userService; - public PackagingService( ILogger logger, IContentService contentService, @@ -1458,6 +1461,65 @@ namespace Umbraco.Core.Services #region Package Manifest #endregion + #region Package Files + + /// + /// This will fetch an Umbraco package file from the package repository and return the relative file path to the downloaded package file + /// + /// + /// + /// /// The current user id performing the operation + /// + public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId) + { + var packageRepo = UmbracoConfig.For.UmbracoSettings().PackageRepositories.GetDefault(); + + using (var httpClient = new HttpClient()) + using (var uow = _uowProvider.CreateUnitOfWork()) + { + //includeHidden = true because we don't care if it's hidden we want to get the file regardless + var url = $"{packageRepo.RestApiUrl}/{packageId}?version={umbracoVersion.ToString(3)}&includeHidden=true&asFile=true"; + byte[] bytes; + try + { + bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult(); + } + catch (HttpRequestException ex) + { + throw new ConnectionException("An error occuring downloading the package from " + url, ex); + } + + //successfull + if (bytes.Length > 0) + { + var packagePath = IOHelper.MapPath(SystemDirectories.Packages); + + // Check for package directory + if (Directory.Exists(packagePath) == false) + Directory.CreateDirectory(packagePath); + + var packageFilePath = Path.Combine(packagePath, packageId + ".umb"); + + using (var fs1 = new FileStream(packageFilePath, FileMode.Create)) + { + fs1.Write(bytes, 0, bytes.Length); + return "packages\\" + packageId + ".umb"; + } + } + + Audit(uow, AuditType.PackagerInstall, $"Package {packageId} fetched from {packageRepo.Id}", userId, -1); + return null; + } + } + + private static void Audit(IUnitOfWork uow, AuditType type, string message, int userId, int objectId) + { + var auditRepo = uow.CreateRepository(); + auditRepo.AddOrUpdate(new AuditItem(objectId, message, type, userId)); + } + + #endregion + #region Templates /// diff --git a/src/Umbraco.Core/StringUdi.cs b/src/Umbraco.Core/StringUdi.cs index 7f1189677f..0f42f4b5f6 100644 --- a/src/Umbraco.Core/StringUdi.cs +++ b/src/Umbraco.Core/StringUdi.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core /// The entity type part of the udi. /// The string id part of the udi. public StringUdi(string entityType, string id) - : base(entityType, "umb://" + entityType + "/" + id) + : base(entityType, "umb://" + entityType + "/" + Uri.EscapeUriString(id)) { Id = id; } @@ -32,7 +32,7 @@ namespace Umbraco.Core public StringUdi(Uri uriValue) : base(uriValue) { - Id = uriValue.AbsolutePath.TrimStart('/'); + Id = Uri.UnescapeDataString(uriValue.AbsolutePath.TrimStart('/')); } /// diff --git a/src/Umbraco.Core/Sync/ConfigServerRegistrar.cs b/src/Umbraco.Core/Sync/ConfigServerRegistrar.cs index 30a1082f1e..5929e307dc 100644 --- a/src/Umbraco.Core/Sync/ConfigServerRegistrar.cs +++ b/src/Umbraco.Core/Sync/ConfigServerRegistrar.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Linq; using System.Web; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; +using Umbraco.Core.Logging; namespace Umbraco.Core.Sync { @@ -17,12 +17,12 @@ namespace Umbraco.Core.Sync private readonly ServerRole _serverRole; private readonly string _umbracoApplicationUrl; - public ConfigServerRegistrar(IUmbracoSettingsSection settings) - : this(settings.DistributedCall) + public ConfigServerRegistrar(IUmbracoSettingsSection settings, ILogger logger) + : this(settings.DistributedCall, logger) { } // for tests - internal ConfigServerRegistrar(IDistributedCallSection settings) + internal ConfigServerRegistrar(IDistributedCallSection settings, ILogger logger) { if (settings.Enabled == false) { @@ -42,6 +42,7 @@ namespace Umbraco.Core.Sync if (serversA.Length == 0) { _serverRole = ServerRole.Unknown; // config error, actually + logger.Debug("Server Role Unknown: DistributedCalls are enabled but no servers are listed."); } else { @@ -50,17 +51,23 @@ namespace Umbraco.Core.Sync var serverName = master.ServerName; if (appId.IsNullOrWhiteSpace() && serverName.IsNullOrWhiteSpace()) + { _serverRole = ServerRole.Unknown; // config error, actually + logger.Debug("Server Role Unknown: Server Name or AppId missing from Server configuration in DistributedCalls settings."); + } else + { _serverRole = IsCurrentServer(appId, serverName) ? ServerRole.Master : ServerRole.Slave; + } } var currentServer = serversA.FirstOrDefault(x => IsCurrentServer(x.AppId, x.ServerName)); if (currentServer != null) { // match, use the configured url + // ReSharper disable once UseStringInterpolation _umbracoApplicationUrl = string.Format("{0}://{1}:{2}/{3}", currentServer.ForceProtocol.IsNullOrWhiteSpace() ? "http" : currentServer.ForceProtocol, currentServer.ServerAddress, @@ -76,19 +83,10 @@ namespace Umbraco.Core.Sync || (serverName.IsNullOrWhiteSpace() == false && serverName.Trim().InvariantEquals(NetworkHelper.MachineName)); } - public IEnumerable Registrations - { - get { return _addresses; } - } + public IEnumerable Registrations => _addresses; - public ServerRole GetCurrentServerRole() - { - return _serverRole; - } + public ServerRole GetCurrentServerRole() => _serverRole; - public string GetCurrentServerUmbracoApplicationUrl() - { - return _umbracoApplicationUrl; - } + public string GetCurrentServerUmbracoApplicationUrl() => _umbracoApplicationUrl; } } diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index 1a27e15a79..b3ea37ebe7 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -103,7 +103,8 @@ namespace Umbraco.Core public override string ToString() { // UriValue is created in the ctor and is never null - return UriValue.ToString(); + // use AbsoluteUri here and not ToString else it's not encoded! + return UriValue.AbsoluteUri; } /// @@ -161,7 +162,7 @@ namespace Umbraco.Core } if (udiType == UdiType.StringUdi) { - udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, path); + udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path)); return true; } if (tryParse) return false; diff --git a/src/Umbraco.Core/UdiGetterExtensions.cs b/src/Umbraco.Core/UdiGetterExtensions.cs index 795d48c259..3d829c8a1a 100644 --- a/src/Umbraco.Core/UdiGetterExtensions.cs +++ b/src/Umbraco.Core/UdiGetterExtensions.cs @@ -198,7 +198,13 @@ namespace Umbraco.Core public static StringUdi GetUdi(this IPartialView entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new StringUdi(Constants.UdiEntityType.PartialView, entity.Path.TrimStart('/')).EnsureClosed(); + + // we should throw on Unknown but for the time being, assume it means PartialView + var entityType = entity.ViewType == PartialViewType.PartialViewMacro + ? Constants.UdiEntityType.PartialViewMacro + : Constants.UdiEntityType.PartialView; + + return new StringUdi(entityType, entity.Path.TrimStart('/')).EnsureClosed(); } /// diff --git a/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs b/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs index fa86cdfb7e..66ec612b16 100644 --- a/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs +++ b/src/Umbraco.Tests/Cache/CacheRefresherComponentTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using Umbraco.Core.Events; using Umbraco.Core.Models; @@ -33,70 +34,70 @@ namespace Umbraco.Tests.Cache new EventDefinition(null, serviceContext.SectionService, new EventArgs(), "Deleted"), new EventDefinition(null, serviceContext.SectionService, new EventArgs(), "New"), - new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs((IUserType) null)), - new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs((IUserType) null)), + new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs((IUser) null)), - new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs((IUser) null)), - new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs((IUser) null)), + new EventDefinition>(null, serviceContext.UserService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.UserService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.LocalizationService, new SaveEventArgs((IDictionaryItem) null)), - new EventDefinition>(null, serviceContext.LocalizationService, new DeleteEventArgs((IDictionaryItem) null)), + new EventDefinition>(null, serviceContext.LocalizationService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.LocalizationService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.DataTypeService, new SaveEventArgs((IDataTypeDefinition) null)), - new EventDefinition>(null, serviceContext.DataTypeService, new DeleteEventArgs((IDataTypeDefinition) null)), + new EventDefinition>(null, serviceContext.DataTypeService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.DataTypeService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.FileService, new SaveEventArgs((Stylesheet) null)), - new EventDefinition>(null, serviceContext.FileService, new DeleteEventArgs((Stylesheet) null)), + new EventDefinition>(null, serviceContext.FileService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.FileService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.DomainService, new SaveEventArgs((IDomain) null)), - new EventDefinition>(null, serviceContext.DomainService, new DeleteEventArgs((IDomain) null)), + new EventDefinition>(null, serviceContext.DomainService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.DomainService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.LocalizationService, new SaveEventArgs((ILanguage) null)), - new EventDefinition>(null, serviceContext.LocalizationService, new DeleteEventArgs((ILanguage) null)), + new EventDefinition>(null, serviceContext.LocalizationService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.LocalizationService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.ContentTypeService, new SaveEventArgs((IContentType) null)), - new EventDefinition>(null, serviceContext.ContentTypeService, new DeleteEventArgs((IContentType) null)), - new EventDefinition>(null, serviceContext.ContentTypeService, new SaveEventArgs((IMediaType) null)), - new EventDefinition>(null, serviceContext.ContentTypeService, new DeleteEventArgs((IMediaType) null)), + new EventDefinition>(null, serviceContext.ContentTypeService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.ContentTypeService, new DeleteEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.ContentTypeService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.ContentTypeService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.MemberTypeService, new SaveEventArgs((IMemberType) null)), - new EventDefinition>(null, serviceContext.MemberTypeService, new DeleteEventArgs((IMemberType) null)), + new EventDefinition>(null, serviceContext.MemberTypeService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.MemberTypeService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.FileService, new SaveEventArgs((ITemplate) null)), - new EventDefinition>(null, serviceContext.FileService, new DeleteEventArgs((ITemplate) null)), + new EventDefinition>(null, serviceContext.FileService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.FileService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.MacroService, new SaveEventArgs((IMacro) null)), - new EventDefinition>(null, serviceContext.MacroService, new DeleteEventArgs((IMacro) null)), + new EventDefinition>(null, serviceContext.MacroService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.MacroService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.MemberService, new SaveEventArgs((IMember) null)), - new EventDefinition>(null, serviceContext.MemberService, new DeleteEventArgs((IMember) null)), + new EventDefinition>(null, serviceContext.MemberService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.MemberService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.MemberGroupService, new SaveEventArgs((IMemberGroup) null)), - new EventDefinition>(null, serviceContext.MemberGroupService, new DeleteEventArgs((IMemberGroup) null)), + new EventDefinition>(null, serviceContext.MemberGroupService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.MemberGroupService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.MediaService, new SaveEventArgs((IMedia) null)), - new EventDefinition>(null, serviceContext.MediaService, new DeleteEventArgs((IMedia) null)), + new EventDefinition>(null, serviceContext.MediaService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.MediaService, new DeleteEventArgs(Enumerable.Empty())), new EventDefinition>(null, serviceContext.MediaService, new MoveEventArgs(new MoveEventInfo(null, "", -1)), "Moved"), new EventDefinition>(null, serviceContext.MediaService, new MoveEventArgs(new MoveEventInfo(null, "", -1)), "Trashed"), new EventDefinition(null, serviceContext.MediaService, new RecycleBinEventArgs(Guid.NewGuid(), new Dictionary>(), true)), - new EventDefinition>(null, serviceContext.ContentService, new SaveEventArgs((IContent) null)), - new EventDefinition>(null, serviceContext.ContentService, new DeleteEventArgs((IContent) null)), + new EventDefinition>(null, serviceContext.ContentService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.ContentService, new DeleteEventArgs(Enumerable.Empty())), new EventDefinition>(null, serviceContext.ContentService, new CopyEventArgs(null, null, -1)), new EventDefinition>(null, serviceContext.ContentService, new MoveEventArgs(new MoveEventInfo(null, "", -1)), "Trashed"), new EventDefinition(null, serviceContext.ContentService, new RecycleBinEventArgs(Guid.NewGuid(), new Dictionary>(), true)), - new EventDefinition>(null, serviceContext.ContentService, new PublishEventArgs((IContent) null), "Published"), - new EventDefinition>(null, serviceContext.ContentService, new PublishEventArgs((IContent) null), "UnPublished"), + new EventDefinition>(null, serviceContext.ContentService, new PublishEventArgs(Enumerable.Empty()), "Published"), + new EventDefinition>(null, serviceContext.ContentService, new PublishEventArgs(Enumerable.Empty()), "UnPublished"), - new EventDefinition>(null, serviceContext.PublicAccessService, new SaveEventArgs((PublicAccessEntry) null)), - new EventDefinition>(null, serviceContext.PublicAccessService, new DeleteEventArgs((PublicAccessEntry) null)), + new EventDefinition>(null, serviceContext.PublicAccessService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.PublicAccessService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.RelationService, new SaveEventArgs((IRelationType) null)), - new EventDefinition>(null, serviceContext.RelationService, new DeleteEventArgs((IRelationType) null)), + new EventDefinition>(null, serviceContext.RelationService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.RelationService, new DeleteEventArgs(Enumerable.Empty())), - new EventDefinition>(null, serviceContext.RelationService, new SaveEventArgs((IRelationType) null)), - new EventDefinition>(null, serviceContext.RelationService, new DeleteEventArgs((IRelationType) null)), + new EventDefinition>(null, serviceContext.RelationService, new SaveEventArgs(Enumerable.Empty())), + new EventDefinition>(null, serviceContext.RelationService, new DeleteEventArgs(Enumerable.Empty())), }; foreach (var definition in definitions) diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs index bdd20fbada..7e7b65108a 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using NUnit.Framework; using Umbraco.Core; @@ -165,6 +166,39 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings public void DisallowedUploadFiles() { Assert.IsTrue(SettingsSection.Content.DisallowedUploadFiles.All(x => "ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd".Split(',').Contains(x))); + } + + [Test] + public void AllowedUploadFiles() + { + Assert.IsTrue(SettingsSection.Content.AllowedUploadFiles.All(x => "jpg,gif,png".Split(',').Contains(x))); + } + + [Test] + [TestCase("png", true)] + [TestCase("jpg", true)] + [TestCase("gif", true)] + // TODO: Why does it flip to TestingDefaults=true for these two tests on AppVeyor. WHY? + //[TestCase("bmp", false)] + //[TestCase("php", false)] + [TestCase("ashx", false)] + [TestCase("config", false)] + public void IsFileAllowedForUpload_WithWhitelist(string extension, bool expected) + { + // Make really sure that defaults are NOT used + TestingDefaults = false; + + Debug.WriteLine("Extension being tested", extension); + Debug.WriteLine("AllowedUploadFiles: {0}", SettingsSection.Content.AllowedUploadFiles); + Debug.WriteLine("DisallowedUploadFiles: {0}", SettingsSection.Content.DisallowedUploadFiles); + + var allowedContainsExtension = SettingsSection.Content.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)); + var disallowedContainsExtension = SettingsSection.Content.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)); + + Debug.WriteLine("AllowedContainsExtension: {0}", allowedContainsExtension); + Debug.WriteLine("DisallowedContainsExtension: {0}", disallowedContainsExtension); + + Assert.AreEqual(SettingsSection.Content.IsFileAllowedForUpload(extension), expected); } } } diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs index 8342bd13a3..01768dd903 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs @@ -1,7 +1,7 @@ using System.Configuration; +using System.Diagnostics; using System.IO; using NUnit.Framework; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.TestHelpers; @@ -9,20 +9,17 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings { public abstract class UmbracoSettingsTests { - - protected virtual bool TestingDefaults - { - get { return false; } - } + protected virtual bool TestingDefaults { get; set; } [SetUp] public void Init() { var config = new FileInfo(TestHelper.MapPathForTest("~/Configurations/UmbracoSettings/web.config")); - - var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName }; - var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); + var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName }; + var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); + + Debug.WriteLine("Testing defaults? {0}", TestingDefaults); if (TestingDefaults) { SettingsSection = configuration.GetSection("umbracoConfiguration/defaultSettings") as UmbracoSettingsSection; @@ -32,8 +29,6 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings SettingsSection = configuration.GetSection("umbracoConfiguration/settings") as UmbracoSettingsSection; } - - Assert.IsNotNull(SettingsSection); } diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config index 7cc941d671..c56ee45f55 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config @@ -92,6 +92,9 @@ ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd + + jpg,png,gif + Textstring diff --git a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs index 50983b92c9..99d5e99085 100644 --- a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs +++ b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Misc private void Initialize(IUmbracoSettingsSection settings) { - _registrar = new ConfigServerRegistrar(settings.DistributedCall); + _registrar = new ConfigServerRegistrar(settings.DistributedCall, Mock.Of()); var container = new ServiceContainer(); container.ConfigureUmbracoCore(); container.Register(_ => _registrar); diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index 957c97c243..b3a1346ba5 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -40,14 +40,14 @@ namespace Umbraco.Tests.Persistence.Repositories { var repository = new PartialViewRepository(unitOfWork, _fileSystem); - var partialView = new PartialView("test-path-1.cshtml") { Content = "// partialView" }; + var partialView = new PartialView(PartialViewType.PartialView, "test-path-1.cshtml") { Content = "// partialView" }; repository.AddOrUpdate(partialView); unitOfWork.Flush(); Assert.IsTrue(_fileSystem.FileExists("test-path-1.cshtml")); Assert.AreEqual("test-path-1.cshtml", partialView.Path); Assert.AreEqual("/Views/Partials/test-path-1.cshtml", partialView.VirtualPath); - partialView = new PartialView("path-2/test-path-2.cshtml") { Content = "// partialView" }; + partialView = new PartialView(PartialViewType.PartialView, "path-2/test-path-2.cshtml") { Content = "// partialView" }; repository.AddOrUpdate(partialView); unitOfWork.Flush(); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.cshtml")); @@ -59,7 +59,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual("path-2\\test-path-2.cshtml", partialView.Path); Assert.AreEqual("/Views/Partials/path-2/test-path-2.cshtml", partialView.VirtualPath); - partialView = new PartialView("path-2\\test-path-3.cshtml") { Content = "// partialView" }; + partialView = new PartialView(PartialViewType.PartialView, "path-2\\test-path-3.cshtml") { Content = "// partialView" }; repository.AddOrUpdate(partialView); unitOfWork.Flush(); Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.cshtml")); @@ -76,7 +76,7 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual("path-2\\test-path-3.cshtml", partialView.Path); Assert.AreEqual("/Views/Partials/path-2/test-path-3.cshtml", partialView.VirtualPath); - partialView = new PartialView("\\test-path-4.cshtml") { Content = "// partialView" }; + partialView = new PartialView(PartialViewType.PartialView, "\\test-path-4.cshtml") { Content = "// partialView" }; Assert.Throws(() => // fixed in 7.3 - 7.2.8 used to strip the \ { repository.AddOrUpdate(partialView); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index aeeabb1368..cf14b80745 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -4,15 +4,18 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core.Events; +using Umbraco.Core.Models; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Scoping; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; namespace Umbraco.Tests.Scoping { [TestFixture] - public class ScopeEventDispatcherTests + public class ScopeEventDispatcherTests //: BaseUmbracoConfigurationTest { [SetUp] public void Setup() @@ -81,7 +84,7 @@ namespace Umbraco.Tests.Scoping var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray(); var knownNames = new[] { "DoThing1", "DoThing2", "DoThing3" }; - var knownArgTypes = new[] { typeof (SaveEventArgs), typeof (SaveEventArgs), typeof (SaveEventArgs) }; + var knownArgTypes = new[] { typeof(SaveEventArgs), typeof(SaveEventArgs), typeof(SaveEventArgs) }; for (var i = 0; i < events.Length; i++) { @@ -91,6 +94,166 @@ namespace Umbraco.Tests.Scoping } } + [Test] + public void SupersededEvents() + { + DoSaveForContent += OnDoThingFail; + DoDeleteForContent += OnDoThingFail; + DoForTestArgs += OnDoThingFail; + DoForTestArgs2 += OnDoThingFail; + + var contentType = MockedContentTypes.CreateBasicContentType(); + + var content1 = MockedContent.CreateBasicContent(contentType); + content1.Id = 123; + + var content2 = MockedContent.CreateBasicContent(contentType); + content2.Id = 456; + + var content3 = MockedContent.CreateBasicContent(contentType); + content3.Id = 789; + + var scopeProvider = new ScopeProvider(Mock.Of(), new Lazy(() => Mock.Of()), Mock.Of()); + using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher())) + { + + //content1 will be filtered from the args + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(new[]{ content1 , content3})); + scope.Events.Dispatch(DoDeleteForContent, this, new DeleteEventArgs(content1)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content2)); + //this entire event will be filtered + scope.Events.Dispatch(DoForTestArgs, this, new TestEventArgs(content1)); + scope.Events.Dispatch(DoForTestArgs2, this, new TestEventArgs2(content1)); + + // events have been queued + var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray(); + Assert.AreEqual(4, events.Length); + + Assert.AreEqual(typeof(SaveEventArgs), events[0].Args.GetType()); + Assert.AreEqual(1, ((SaveEventArgs)events[0].Args).SavedEntities.Count()); + Assert.AreEqual(content3.Id, ((SaveEventArgs)events[0].Args).SavedEntities.First().Id); + + Assert.AreEqual(typeof(DeleteEventArgs), events[1].Args.GetType()); + Assert.AreEqual(content1.Id, ((DeleteEventArgs) events[1].Args).DeletedEntities.First().Id); + + Assert.AreEqual(typeof(SaveEventArgs), events[2].Args.GetType()); + Assert.AreEqual(content2.Id, ((SaveEventArgs)events[2].Args).SavedEntities.First().Id); + + Assert.AreEqual(typeof(TestEventArgs2), events[3].Args.GetType()); + } + } + + /// + /// This will test that when we track events that before we Get the events we normalize all of the + /// event entities to be the latest one (most current) found amongst the event so that there is + /// no 'stale' entities in any of the args + /// + [Test] + public void LatestEntities() + { + DoSaveForContent += OnDoThingFail; + + var now = DateTime.Now; + var contentType = MockedContentTypes.CreateBasicContentType(); + var content1 = MockedContent.CreateBasicContent(contentType); + content1.Id = 123; + content1.UpdateDate = now.AddMinutes(1); + var content2 = MockedContent.CreateBasicContent(contentType); + content2.Id = 123; + content2.UpdateDate = now.AddMinutes(2); + var content3 = MockedContent.CreateBasicContent(contentType); + content3.Id = 123; + content3.UpdateDate = now.AddMinutes(3); + + var scopeProvider = new ScopeProvider(Mock.Of(), new Lazy(() => Mock.Of()), Mock.Of()); + using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher())) + { + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content1)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content2)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content3)); + + // events have been queued + var events = scope.Events.GetEvents(EventDefinitionFilter.All).ToArray(); + Assert.AreEqual(3, events.Length); + + foreach (var t in events) + { + var args = (SaveEventArgs)t.Args; + foreach (var entity in args.SavedEntities) + { + Assert.AreEqual(content3, entity); + Assert.IsTrue(object.ReferenceEquals(content3, entity)); + } + } + } + } + + [Test] + public void FirstIn() + { + DoSaveForContent += OnDoThingFail; + + var now = DateTime.Now; + var contentType = MockedContentTypes.CreateBasicContentType(); + var content1 = MockedContent.CreateBasicContent(contentType); + content1.Id = 123; + content1.UpdateDate = now.AddMinutes(1); + var content2 = MockedContent.CreateBasicContent(contentType); + content2.Id = 123; + content1.UpdateDate = now.AddMinutes(2); + var content3 = MockedContent.CreateBasicContent(contentType); + content3.Id = 123; + content1.UpdateDate = now.AddMinutes(3); + + var scopeProvider = new ScopeProvider(Mock.Of(), new Lazy(() => Mock.Of()), Mock.Of()); + using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher())) + { + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content1)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content2)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content3)); + + // events have been queued + var events = scope.Events.GetEvents(EventDefinitionFilter.FirstIn).ToArray(); + Assert.AreEqual(1, events.Length); + Assert.AreEqual(content1, ((SaveEventArgs) events[0].Args).SavedEntities.First()); + Assert.IsTrue(object.ReferenceEquals(content1, ((SaveEventArgs)events[0].Args).SavedEntities.First())); + Assert.AreEqual(content1.UpdateDate, ((SaveEventArgs) events[0].Args).SavedEntities.First().UpdateDate); + } + } + + [Test] + public void LastIn() + { + DoSaveForContent += OnDoThingFail; + + var now = DateTime.Now; + var contentType = MockedContentTypes.CreateBasicContentType(); + var content1 = MockedContent.CreateBasicContent(contentType); + content1.Id = 123; + content1.UpdateDate = now.AddMinutes(1); + var content2 = MockedContent.CreateBasicContent(contentType); + content2.Id = 123; + content2.UpdateDate = now.AddMinutes(2); + var content3 = MockedContent.CreateBasicContent(contentType); + content3.Id = 123; + content3.UpdateDate = now.AddMinutes(3); + + var scopeProvider = new ScopeProvider(Mock.Of(), new Lazy(() => Mock.Of()), Mock.Of()); + using (var scope = scopeProvider.CreateScope(eventDispatcher: new PassiveEventDispatcher())) + { + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content1)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content2)); + scope.Events.Dispatch(DoSaveForContent, this, new SaveEventArgs(content3)); + + // events have been queued + var events = scope.Events.GetEvents(EventDefinitionFilter.LastIn).ToArray(); + Assert.AreEqual(1, events.Length); + Assert.AreEqual(content3, ((SaveEventArgs)events[0].Args).SavedEntities.First()); + Assert.IsTrue(object.ReferenceEquals(content3, ((SaveEventArgs)events[0].Args).SavedEntities.First())); + Assert.AreEqual(content3.UpdateDate, ((SaveEventArgs)events[0].Args).SavedEntities.First().UpdateDate); + } + } + [TestCase(true)] [TestCase(false)] public void EventsDispatching_Passive(bool complete) @@ -179,12 +342,40 @@ namespace Umbraco.Tests.Scoping Assert.Fail(); } + public static event EventHandler> DoSaveForContent; + public static event EventHandler> DoDeleteForContent; + public static event EventHandler DoForTestArgs; + public static event EventHandler DoForTestArgs2; public static event EventHandler> DoThing1; - public static event EventHandler> DoThing2; public static event TypedEventHandler> DoThing3; + public class TestEventArgs : CancellableObjectEventArgs + { + public TestEventArgs(object eventObject) : base(eventObject) + { + } + + public object MyEventObject + { + get { return EventObject; } + } + } + + [SupersedeEvent(typeof(TestEventArgs))] + public class TestEventArgs2 : CancellableObjectEventArgs + { + public TestEventArgs2(object eventObject) : base(eventObject) + { + } + + public object MyEventObject + { + get { return EventObject; } + } + } + public class PassiveEventDispatcher : QueuingEventDispatcherBase { public PassiveEventDispatcher() diff --git a/src/Umbraco.Tests/Scoping/ScopeTests.cs b/src/Umbraco.Tests/Scoping/ScopeTests.cs index 7e2fb58a17..fdb8927932 100644 --- a/src/Umbraco.Tests/Scoping/ScopeTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeTests.cs @@ -533,6 +533,44 @@ namespace Umbraco.Tests.Scoping Assert.IsNotNull(ambientContext); // the context is still there } + [TestCase(true)] + [TestCase(false)] + public void ScopeContextEnlistAgain(bool complete) + { + var scopeProvider = ScopeProvider as IScopeProviderInternal; + + bool? completed = null; + Exception exception = null; + + Assert.IsNull(scopeProvider.AmbientScope); + using (var scope = scopeProvider.CreateScope()) + { + scopeProvider.Context.Enlist("name", c => + { + completed = c; + + // at that point the scope is gone, but the context is still there + var ambientContext = scopeProvider.AmbientContext; + + try + { + ambientContext.Enlist("another", c2 => { }); + } + catch (Exception e) + { + exception = e; + } + }); + if (complete) + scope.Complete(); + } + Assert.IsNull(scopeProvider.AmbientScope); + Assert.IsNull(scopeProvider.AmbientContext); + Assert.IsNotNull(completed); + Assert.IsNotNull(exception); + Assert.IsInstanceOf(exception); + } + [Test] public void ScopeContextException() { diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 16f45c4e54..348901c3fe 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -154,7 +154,9 @@ namespace Umbraco.Tests.Scoping // scope.Complete(); // } - // Assert.AreEqual(complete ? 2 : 0, evented); + //The reason why there is only 1 event occuring is because we are publishing twice for the same event for the same + //object and the scope deduplicates the events (uses the latest) + // Assert.AreEqual(complete ? 1 : 0, evented); // // this should never change // Assert.AreEqual(beforeOuterXml, beforeXml.OuterXml); diff --git a/src/Umbraco.Tests/UdiTests.cs b/src/Umbraco.Tests/UdiTests.cs index 9b803d5fa3..6e7e4671a9 100644 --- a/src/Umbraco.Tests/UdiTests.cs +++ b/src/Umbraco.Tests/UdiTests.cs @@ -31,6 +31,34 @@ namespace Umbraco.Tests Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString()); } + [Test] + public void StringEncodingTest() + { + // absolute path is unescaped + var uri = new Uri("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test"); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this is a test", uri.ToString()); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test", uri.AbsoluteUri); + Assert.AreEqual("/this%20is%20a%20test", uri.AbsolutePath); + + Assert.AreEqual("/this is a test", Uri.UnescapeDataString(uri.AbsolutePath)); + Assert.AreEqual("%2Fthis%20is%20a%20test", Uri.EscapeDataString("/this is a test")); + Assert.AreEqual("/this%20is%20a%20test", Uri.EscapeUriString("/this is a test")); + + var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test"); + Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType); + Assert.IsInstanceOf(udi); + var stringEntityId = udi as StringUdi; + Assert.IsNotNull(stringEntityId); + Assert.AreEqual("this is a test", stringEntityId.Id); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test", udi.ToString()); + + var udi2 = new StringUdi(Constants.UdiEntityType.AnyString, "this is a test"); + Assert.AreEqual(udi, udi2); + + var udi3 = new StringUdi(Constants.UdiEntityType.AnyString, "path to/this is a test.xyz"); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/path%20to/this%20is%20a%20test.xyz", udi3.ToString()); + } + [Test] public void GuidEntityCtorTest() { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js index 2859cd8a8a..e47032fed3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js @@ -105,14 +105,14 @@ angular.module("umbraco.directives") }); //// INIT ///// - $image.load(function(){ - $timeout(function(){ - setDimensions(); - scope.loaded = true; - if (scope.onImageLoaded) { - scope.onImageLoaded(); - } - }); + $image.load(function() { + $timeout(function() { + setDimensions(); + scope.loaded = true; + if (angular.isFunction(scope.onImageLoaded)) { + scope.onImageLoaded(); + } + }); }); $(window).on('resize.umbImageGravity', function(){ diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/ourpackagerrepository.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/ourpackagerrepository.resource.js index 053aaf1394..f803d7edce 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/ourpackagerrepository.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/ourpackagerrepository.resource.js @@ -5,15 +5,14 @@ **/ function ourPackageRepositoryResource($q, $http, umbDataFormatter, umbRequestHelper) { - //var baseurl = "http://localhost:24292/webapi/packages/v1"; - var baseurl = "https://our.umbraco.org/webapi/packages/v1"; + var baseurl = Umbraco.Sys.ServerVariables.umbracoUrls.packagesRestApiBaseUrl; return { getDetails: function (packageId) { return umbRequestHelper.resourcePromise( - $http.get(baseurl + "/" + packageId), + $http.get(baseurl + "/" + packageId + "?version=" + Umbraco.Sys.ServerVariables.application.version), 'Failed to get package details'); }, diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html b/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html index ec45b652c9..4edf2eda25 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/upgrade.html @@ -5,7 +5,7 @@

- To read a report of changes between your current version {{installer.current.model.currentVersion}} and this version your upgrading to {{installer.current.model.newVersion}} + To read a report of changes between your current version {{installer.current.model.currentVersion}} and this version you're upgrading to {{installer.current.model.newVersion}}

View Report diff --git a/src/Umbraco.Web.UI.Client/src/less/tree.less b/src/Umbraco.Web.UI.Client/src/less/tree.less index f2815f445c..df1bc4114a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/tree.less @@ -49,7 +49,7 @@ .umb-tree li.current > div i.icon, .umb-tree li.current > div ins { color: @white !important; - background: @turquoise-d1; + background-color: @turquoise-d1; border-color: @turquoise-d1; } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html index c090cac20c..65ce1c3ecb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html @@ -50,7 +50,7 @@

- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.html index 3e40c79b7d..70a4ccb8b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.html @@ -6,7 +6,8 @@ placeholder="@general_url" class="umb-editor umb-textstring" ng-model="model.target.url" - ng-disabled="model.target.id"/> + ng-disabled="model.target.id" + focus-when="{{true}} "/> diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js index 7010a0db9d..d5e4301335 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js @@ -15,15 +15,23 @@ angular.module("umbraco") $scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false; $scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1; $scope.cropSize = dialogOptions.cropSize; - $scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId"); - if ($scope.onlyImages) { - $scope.acceptedFileTypes = mediaHelper - .formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes); - } else { - $scope.acceptedFileTypes = !mediaHelper - .formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles); - } - $scope.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; + $scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId"); + + var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings; + var allowedUploadFiles = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles); + if ($scope.onlyImages) { + $scope.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.imageFileTypes); + } else { + // Use whitelist of allowed file types if provided + if (allowedUploadFiles !== '') { + $scope.acceptedFileTypes = allowedUploadFiles; + } else { + // If no whitelist, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles + $scope.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles); + } + } + + $scope.maxFileSize = umbracoSettings.maxFileSize + "KB"; $scope.model.selectedImages = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js index 979428de0c..ea9ad6ca97 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js @@ -1,14 +1,13 @@ -(function () { +(function() { "use strict"; function QueryBuilderOverlayController($scope, templateQueryResource, localizationService) { - var everything = localizationService.localize("template_allContent"); - var myWebsite = localizationService.localize("template_websiteRoot"); + var everything = ""; + var myWebsite = ""; + var ascendingTranslation = ""; + var descendingTranslation = ""; - var ascendingTranslation = localizationService.localize("template_ascending"); - var descendingTranslation = localizationService.localize("template_descending"); - var vm = this; vm.properties = []; @@ -21,34 +20,6 @@ format: "YYYY-MM-DD" }; - vm.query = { - contentType: { - name: everything - }, - source: { - name: myWebsite - }, - filters: [ - { - property: undefined, - operator: undefined - } - ], - sort: { - property: { - alias: "", - name: "", - }, - direction: "ascending", //This is the value for sorting sent to server - translation: { - currentLabel: ascendingTranslation, //This is the localized UI value in the the dialog - ascending: ascendingTranslation, - descending: descendingTranslation - } - - } - }; - vm.chooseSource = chooseSource; vm.getPropertyOperators = getPropertyOperators; vm.addFilter = addFilter; @@ -63,21 +34,48 @@ function onInit() { + vm.query = { + contentType: { + name: everything + }, + source: { + name: myWebsite + }, + filters: [ + { + property: undefined, + operator: undefined + } + ], + sort: { + property: { + alias: "", + name: "", + }, + direction: "ascending", //This is the value for sorting sent to server + translation: { + currentLabel: ascendingTranslation, //This is the localized UI value in the the dialog + ascending: ascendingTranslation, + descending: descendingTranslation + } + } + }; + templateQueryResource.getAllowedProperties() - .then(function (properties) { + .then(function(properties) { vm.properties = properties; }); templateQueryResource.getContentTypes() - .then(function (contentTypes) { + .then(function(contentTypes) { vm.contentTypes = contentTypes; }); templateQueryResource.getFilterConditions() - .then(function (conditions) { + .then(function(conditions) { vm.conditions = conditions; }); - + throttledFunc(); } @@ -111,10 +109,11 @@ } function getPropertyOperators(property) { - var conditions = _.filter(vm.conditions, function (condition) { - var index = condition.appliesTo.indexOf(property.type); - return index >= 0; - }); + var conditions = _.filter(vm.conditions, + function(condition) { + var index = condition.appliesTo.indexOf(property.type); + return index >= 0; + }); return conditions; } @@ -123,10 +122,8 @@ } function trashFilter(query, filter) { - for (var i = 0; i < query.filters.length; i++) - { - if (query.filters[i] == filter) - { + for (var i = 0; i < query.filters.length; i++) { + if (query.filters[i] == filter) { query.filters.splice(i, 1); } } @@ -173,7 +170,7 @@ function setFilterTerm(filter, term) { filter.term = term; - if(filter.constraintValue) { + if (filter.constraintValue) { throttledFunc(); } } @@ -183,22 +180,32 @@ } function datePickerChange(event, filter) { - if(event.date && event.date.isValid()) { + if (event.date && event.date.isValid()) { filter.constraintValue = event.date.format(vm.datePickerConfig.format); throttledFunc(); } } - var throttledFunc = _.throttle(function () { - - templateQueryResource.postTemplateQuery(vm.query) - .then(function (response) { - $scope.model.result = response; - }); + var throttledFunc = _.throttle(function() { - }, 200); + templateQueryResource.postTemplateQuery(vm.query) + .then(function(response) { + $scope.model.result = response; + }); - onInit(); + }, + 200); + + localizationService.localizeMany([ + "template_allContent", "template_websiteRoot", "template_ascending", "template_descending" + ]) + .then(function(res) { + everything = res[0]; + myWebsite = res[1]; + ascendingTranslation = res[2]; + descendingTranslation = res[3]; + onInit(); + }); } angular.module("umbraco").controller("Umbraco.Overlays.QueryBuilderController", QueryBuilderOverlayController); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html index f30851e62e..7c5f0f728f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html @@ -1,5 +1,5 @@
-
+
@@ -12,10 +12,10 @@
- {{item.name}} + {{item.name}} - {{item.name}} + {{item.name}} {{item.name}} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js index df21541f09..3c8170e54b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js @@ -138,15 +138,15 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag //cannot just check for !newVal because it might be an empty string which we //want to look for. if (newVal !== null && newVal !== undefined && newVal !== oldVal) { - //now we need to check if we need to re-initialize our structure which is kind of tricky - // since we only want to do that if the server has changed the value, not if this controller - // has changed the value. There's only 2 scenarios where we change the value internall so - // we know what those values can be, if they are not either of them, then we'll re-initialize. - - if (newVal.clearFiles !== true && newVal !== $scope.originalValue && !newVal.selectedFiles) { + // here we need to check if the value change needs to trigger an update in the UI. + // if the value is only changed in the controller and not in the server values, we do not + // want to trigger an update yet. + // we can however no longer rely on checking values in the controller vs. values from the server + // to determine whether to update or not, since you could potentially be uploading a file with + // the exact same name - in that case we need to reinitialize to show the newly uploaded file. + if (newVal.clearFiles !== true && !newVal.selectedFiles) { initialize($scope.rebuildInput.index + 1); } - } }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js index e289a389cb..bb580a906d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js @@ -1,10 +1,17 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.Grid.MediaController", - function ($scope, $rootScope, $timeout) { + function ($scope, $rootScope, $timeout, userService) { + + if (!$scope.model.config.startNodeId) { + userService.getCurrentUser().then(function (userData) { + $scope.model.config.startNodeId = userData.startMediaId; + }); + } $scope.setImage = function(){ $scope.mediaPickerOverlay = {}; $scope.mediaPickerOverlay.view = "mediapicker"; + $scope.mediaPickerOverlay.startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined; $scope.mediaPickerOverlay.cropSize = $scope.control.editor.config && $scope.control.editor.config.size ? $scope.control.editor.config.size : undefined; $scope.mediaPickerOverlay.showDetails = true; $scope.mediaPickerOverlay.disableFolderSelect = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js index b8ba4f880b..9a28627aa1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.listviewlayout.controller.js @@ -6,118 +6,124 @@ * @description * The controller for the content type editor */ -(function() { - "use strict"; +(function () { + "use strict"; - function ListViewGridLayoutController($scope, $routeParams, mediaHelper, mediaResource, $location, listViewHelper, mediaTypeHelper) { + function ListViewGridLayoutController($scope, $routeParams, mediaHelper, mediaResource, $location, listViewHelper, mediaTypeHelper) { - var vm = this; + var vm = this; + var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings; - vm.nodeId = $scope.contentId; - //we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles - vm.acceptedFileTypes = !mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles); - vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; - vm.activeDrag = false; - vm.mediaDetailsTooltip = {}; - vm.itemsWithoutFolders = []; - vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20'; - vm.acceptedMediatypes = []; + vm.nodeId = $scope.contentId; + // Use whitelist of allowed file types if provided + vm.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles); + if (vm.acceptedFileTypes === '') { + // If not provided, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles + vm.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles); + } - vm.dragEnter = dragEnter; - vm.dragLeave = dragLeave; - vm.onFilesQueue = onFilesQueue; - vm.onUploadComplete = onUploadComplete; + vm.maxFileSize = umbracoSettings.maxFileSize + "KB"; + vm.activeDrag = false; + vm.mediaDetailsTooltip = {}; + vm.itemsWithoutFolders = []; + vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20'; + vm.acceptedMediatypes = []; - vm.hoverMediaItemDetails = hoverMediaItemDetails; - vm.selectContentItem = selectContentItem; - vm.selectItem = selectItem; - vm.selectFolder = selectFolder; - vm.goToItem = goToItem; + vm.dragEnter = dragEnter; + vm.dragLeave = dragLeave; + vm.onFilesQueue = onFilesQueue; + vm.onUploadComplete = onUploadComplete; - function activate() { - vm.itemsWithoutFolders = filterOutFolders($scope.items); + vm.hoverMediaItemDetails = hoverMediaItemDetails; + vm.selectContentItem = selectContentItem; + vm.selectItem = selectItem; + vm.selectFolder = selectFolder; + vm.goToItem = goToItem; - //no need to make another REST/DB call if this data is not used when we are browsing the bin - if ($scope.entityType === 'media' && !vm.isRecycleBin) { - mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) { - vm.acceptedMediatypes = types; - }); - } + function activate() { + vm.itemsWithoutFolders = filterOutFolders($scope.items); - } + //no need to make another REST/DB call if this data is not used when we are browsing the bin + if ($scope.entityType === 'media' && !vm.isRecycleBin) { + mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) { + vm.acceptedMediatypes = types; + }); + } - function filterOutFolders(items) { + } - var newArray = []; + function filterOutFolders(items) { - if(items && items.length ) { + var newArray = []; - for (var i = 0; items.length > i; i++) { - var item = items[i]; - var isFolder = !mediaHelper.hasFilePropertyType(item); + if (items && items.length) { - if (!isFolder) { - newArray.push(item); - } - } + for (var i = 0; items.length > i; i++) { + var item = items[i]; + var isFolder = !mediaHelper.hasFilePropertyType(item); - } + if (!isFolder) { + newArray.push(item); + } + } - return newArray; - } + } - function dragEnter(el, event) { - vm.activeDrag = true; - } + return newArray; + } - function dragLeave(el, event) { - vm.activeDrag = false; - } + function dragEnter(el, event) { + vm.activeDrag = true; + } - function onFilesQueue() { - vm.activeDrag = false; - } + function dragLeave(el, event) { + vm.activeDrag = false; + } - function onUploadComplete() { - $scope.getContent($scope.contentId); - } + function onFilesQueue() { + vm.activeDrag = false; + } - function hoverMediaItemDetails(item, event, hover) { + function onUploadComplete() { + $scope.getContent($scope.contentId); + } - if (hover && !vm.mediaDetailsTooltip.show) { + function hoverMediaItemDetails(item, event, hover) { - vm.mediaDetailsTooltip.event = event; - vm.mediaDetailsTooltip.item = item; - vm.mediaDetailsTooltip.show = true; + if (hover && !vm.mediaDetailsTooltip.show) { - } else if (!hover && vm.mediaDetailsTooltip.show) { + vm.mediaDetailsTooltip.event = event; + vm.mediaDetailsTooltip.item = item; + vm.mediaDetailsTooltip.show = true; - vm.mediaDetailsTooltip.show = false; + } else if (!hover && vm.mediaDetailsTooltip.show) { - } + vm.mediaDetailsTooltip.show = false; - } + } - function selectContentItem(item, $event, $index) { - listViewHelper.selectHandler(item, $index, $scope.items, $scope.selection, $event); - } + } - function selectItem(item, $event, $index) { - listViewHelper.selectHandler(item, $index, vm.itemsWithoutFolders, $scope.selection, $event); - } + function selectContentItem(item, $event, $index) { + listViewHelper.selectHandler(item, $index, $scope.items, $scope.selection, $event); + } - function selectFolder(folder, $event, $index) { - listViewHelper.selectHandler(folder, $index, $scope.folders, $scope.selection, $event); - } + function selectItem(item, $event, $index) { + listViewHelper.selectHandler(item, $index, vm.itemsWithoutFolders, $scope.selection, $event); + } - function goToItem(item, $event, $index) { - $location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + item.id); - } + function selectFolder(folder, $event, $index) { + listViewHelper.selectHandler(folder, $index, $scope.folders, $scope.selection, $event); + } - activate(); + function goToItem(item, $event, $index) { + $location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + item.id); + } - } + activate(); - angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.GridLayoutController", ListViewGridLayoutController); + } + + angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.GridLayoutController", ListViewGridLayoutController); })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js index 15c2042477..799cc5894c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js @@ -1,89 +1,96 @@ (function () { - "use strict"; + "use strict"; - function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper, mediaTypeHelper) { + function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper, mediaTypeHelper) { - var vm = this; + var vm = this; + var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings; - vm.nodeId = $scope.contentId; - //we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles - vm.acceptedFileTypes = !mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles); - vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; - vm.activeDrag = false; - vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20'; - vm.acceptedMediatypes = []; + vm.nodeId = $scope.contentId; - vm.selectItem = selectItem; - vm.clickItem = clickItem; - vm.selectAll = selectAll; - vm.isSelectedAll = isSelectedAll; - vm.isSortDirection = isSortDirection; - vm.sort = sort; - vm.dragEnter = dragEnter; - vm.dragLeave = dragLeave; - vm.onFilesQueue = onFilesQueue; - vm.onUploadComplete = onUploadComplete; - - function activate() { - - if ($scope.entityType === 'media') { - mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) { - vm.acceptedMediatypes = types; - }); + // Use whitelist of allowed file types if provided + vm.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles); + if (vm.acceptedFileTypes === '') { + // If not provided, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles + vm.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles); } - } + vm.maxFileSize = umbracoSettings.maxFileSize + "KB"; + vm.activeDrag = false; + vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20'; + vm.acceptedMediatypes = []; - function selectAll($event) { - listViewHelper.selectAllItems($scope.items, $scope.selection, $event); - } + vm.selectItem = selectItem; + vm.clickItem = clickItem; + vm.selectAll = selectAll; + vm.isSelectedAll = isSelectedAll; + vm.isSortDirection = isSortDirection; + vm.sort = sort; + vm.dragEnter = dragEnter; + vm.dragLeave = dragLeave; + vm.onFilesQueue = onFilesQueue; + vm.onUploadComplete = onUploadComplete; - function isSelectedAll() { - return listViewHelper.isSelectedAll($scope.items, $scope.selection); - } + function activate() { - function selectItem(selectedItem, $index, $event) { - listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event); - } + if ($scope.entityType === 'media') { + mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) { + vm.acceptedMediatypes = types; + }); + } - function clickItem(item) { - // if item.id is 2147483647 (int.MaxValue) use item.key - $location.path($scope.entityType + '/' +$scope.entityType + '/edit/' + (item.id === 2147483647 ? item.key : item.id)); - } + } - function isSortDirection(col, direction) { - return listViewHelper.setSortingDirection(col, direction, $scope.options); - } + function selectAll($event) { + listViewHelper.selectAllItems($scope.items, $scope.selection, $event); + } - function sort(field, allow, isSystem) { - if (allow) { - $scope.options.orderBySystemField = isSystem; - listViewHelper.setSorting(field, allow, $scope.options); + function isSelectedAll() { + return listViewHelper.isSelectedAll($scope.items, $scope.selection); + } + + function selectItem(selectedItem, $index, $event) { + listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event); + } + + function clickItem(item) { + // if item.id is 2147483647 (int.MaxValue) use item.key + $location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + (item.id === 2147483647 ? item.key : item.id)); + } + + function isSortDirection(col, direction) { + return listViewHelper.setSortingDirection(col, direction, $scope.options); + } + + function sort(field, allow, isSystem) { + if (allow) { + $scope.options.orderBySystemField = isSystem; + listViewHelper.setSorting(field, allow, $scope.options); + $scope.getContent($scope.contentId); + } + } + + // Dropzone upload functions + function dragEnter(el, event) { + vm.activeDrag = true; + } + + function dragLeave(el, event) { + vm.activeDrag = false; + } + + function onFilesQueue() { + vm.activeDrag = false; + } + + function onUploadComplete() { $scope.getContent($scope.contentId); - } - } + } - // Dropzone upload functions - function dragEnter(el, event) { - vm.activeDrag = true; - } + activate(); - function dragLeave(el, event) { - vm.activeDrag = false; - } + } - function onFilesQueue() { - vm.activeDrag = false; - } + angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.ListLayoutController", ListViewListLayoutController); - function onUploadComplete() { - $scope.getContent($scope.contentId); - } - - activate(); - - } - -angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.ListLayoutController", ListViewListLayoutController); - -}) (); +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index dafe6cc3c7..6652c52cc0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -112,10 +112,9 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl // content picker. THen we don't have to worry about setting ids, render models, models, we just set one and let the // watch do all the rest. $timeout(function(){ - angular.forEach($scope.images, function(value, key){ - r.push(value.id); + angular.forEach($scope.images, function(value, key) { + r.push($scope.model.config.idType === "udi" ? value.udi : value.id); }); - $scope.ids = r; $scope.sync(); }, 500, false); diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 45dba79ad5..5d2129668e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -60,10 +60,13 @@ // sync tree // if master template alias has changed move the node to it's new location if(oldMasterTemplateAlias !== vm.template.masterTemplateAlias) { - - // move node to new location in tree - //first we need to remove the node that we're working on - treeService.removeNode(vm.page.menu.currentNode); + + // When creating a new template the id is -1. Make sure We don't remove the root node. + if (vm.page.menu.currentNode.id !== "-1") { + // move node to new location in tree + //first we need to remove the node that we're working on + treeService.removeNode(vm.page.menu.currentNode); + } // update stored alias to the new one so the node won't move again unless the alias is changed again oldMasterTemplateAlias = vm.template.masterTemplateAlias; diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index c69a3e638e..a8491fcf6f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -15,7 +15,7 @@ {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} OnBuildSuccess true - 44319 + enabled disabled false @@ -482,13 +482,6 @@ Properties\SolutionInfo.cs - - loadStarterKits.ascx - ASPXCodeBehind - - - loadStarterKits.ascx - noNodes.aspx ASPXCodeBehind @@ -566,13 +559,6 @@ directoryBrowser.aspx - - StarterKits.aspx - ASPXCodeBehind - - - StarterKits.aspx - ChangeDocType.aspx ASPXCodeBehind @@ -668,7 +654,6 @@ - @@ -816,7 +801,6 @@ - @@ -859,7 +843,6 @@ - @@ -878,12 +861,8 @@ - - - - @@ -1131,7 +1110,26 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll + + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll + + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll + + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll + + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll + + + + + diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index ddf4ff07c7..b98d36a9a4 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -93,6 +93,9 @@ ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,svg,php,htaccess + + + Textstring diff --git a/src/Umbraco.Web.UI/umbraco/Install/Legacy/LoadStarterKits.ascx.cs b/src/Umbraco.Web.UI/umbraco/Install/Legacy/LoadStarterKits.ascx.cs deleted file mode 100644 index d205a93963..0000000000 --- a/src/Umbraco.Web.UI/umbraco/Install/Legacy/LoadStarterKits.ascx.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using System.Web.Routing; -using System.Web.UI; -using Umbraco.Core.Logging; -using Umbraco.Web.Install; - -namespace Umbraco.Web.UI.Install.Steps.Skinning -{ - public delegate void StarterKitInstalledEventHandler(); - - public partial class LoadStarterKits : UserControl - { - /// - /// Returns the string for the package installer web service base url - /// - protected string PackageInstallServiceBaseUrl { get; private set; } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - //Get the URL for the package install service base url - var umbracoPath = Core.Configuration.GlobalSettings.UmbracoMvcArea; - var urlHelper = new UrlHelper(Context.Request.RequestContext); - //PackageInstallServiceBaseUrl = urlHelper.Action("Index", "InstallPackage", new { area = "UmbracoInstall" }); - PackageInstallServiceBaseUrl = urlHelper.GetUmbracoApiService("Index", "InstallPackage", "UmbracoInstall"); - } - - /// - /// Flag to show if we can connect to the repo or not - /// - protected bool CannotConnect { get; private set; } - - public event StarterKitInstalledEventHandler StarterKitInstalled; - - protected virtual void OnStarterKitInstalled() - { - StarterKitInstalled(); - } - - - private readonly global::umbraco.cms.businesslogic.packager.repositories.Repository _repo; - private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; - - public LoadStarterKits() - { - _repo = global::umbraco.cms.businesslogic.packager.repositories.Repository.getByGuid(RepoGuid); - } - - protected void Page_Load(object sender, EventArgs e) - { - - } - - //protected void NextStep(object sender, EventArgs e) - //{ - // var p = (Default)this.Page; - // //InstallHelper.RedirectToNextStep(Page, Request.GetItemAsString("installStep")); - //} - - protected override void OnInit(EventArgs e) - { - base.OnInit(e); - - if (_repo == null) - { - throw new InvalidOperationException("Could not find repository with id " + RepoGuid); - } - - //clear progressbar cache - //InstallHelper.ClearProgress(); - - if (_repo.HasConnection()) - { - try - { - var r = new org.umbraco.our.Repository(); - - rep_starterKits.DataSource = r.Modules(); - rep_starterKits.DataBind(); - } - catch (Exception ex) - { - Current.Logger.Error("Cannot connect to package repository", ex); - CannotConnect = true; - - } - } - else - { - CannotConnect = true; - } - } - - - protected void GotoLastStep(object sender, EventArgs e) - { - //InstallHelper.RedirectToLastStep(Page); - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/Install/Legacy/LoadStarterKits.ascx.designer.cs b/src/Umbraco.Web.UI/umbraco/Install/Legacy/LoadStarterKits.ascx.designer.cs deleted file mode 100644 index f9f25ad3a1..0000000000 --- a/src/Umbraco.Web.UI/umbraco/Install/Legacy/LoadStarterKits.ascx.designer.cs +++ /dev/null @@ -1,60 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Web.UI.Install.Steps.Skinning { - - - public partial class LoadStarterKits { - - /// - /// pl_loadStarterKits control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder pl_loadStarterKits; - - /// - /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// rep_starterKits control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater rep_starterKits; - - /// - /// LinkButton1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton LinkButton1; - - /// - /// LinkButton2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton LinkButton2; - } -} diff --git a/src/Umbraco.Web.UI/umbraco/Install/Legacy/loadStarterKits.ascx b/src/Umbraco.Web.UI/umbraco/Install/Legacy/loadStarterKits.ascx deleted file mode 100644 index 490ff5b3ba..0000000000 --- a/src/Umbraco.Web.UI/umbraco/Install/Legacy/loadStarterKits.ascx +++ /dev/null @@ -1,98 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="LoadStarterKits.ascx.cs" Inherits="Umbraco.Web.UI.Install.Steps.Skinning.LoadStarterKits" %> -<%@ Import Namespace="Umbraco.Web.org.umbraco.our" %> - -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - <% if (!CannotConnect) { %> - - <% } %> - - - -
    - - -
  • "> -
    - <%# ((Package)Container.DataItem).Text %> - -

    <%# ((Package)Container.DataItem).Text %>

    - <%# ((Package)Container.DataItem).Description %> - - - Install - -
    -
  • -
    - -
- <%-- - No thanks, do not install a starterkit! - --%> - -
- -
- -
"> - -
-

Oops...the installer can't connect to the repository

- Starter Kits could not be fetched from the repository as there was no connection - which can occur if you are using a proxy server or firewall with certain configurations, - or if you are not currently connected to the internet. -
- Click Continue to complete the installation then navigate to the Developer section of your Umbraco installation - where you will find the Starter Kits listed in the Packages tree. -
- - -
-
 
- Continue -
- -
- - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index a6b7766eac..9cf5077d9d 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -150,7 +150,7 @@ Udgivelsesdato Dato for Fortryd udgivelse Fjern dato - Sorteringrækkefølgen er opdateret + Sorteringsrækkefølgen er opdateret For at sortere, træk siderne eller klik på en af kolonnehovederne. Du kan vælge flere sider ved at holde "shift" eller "control" nede mens du vælger. Statistik Titel (valgfri) @@ -184,7 +184,7 @@ Vælg en type og skriv en titel "dokument typer".]]> "media typer".]]> - Dokument type uden skabelon + Dokumenttype uden skabelon Ny mappe Ny datatype @@ -320,6 +320,7 @@ Søg... Filtrer... Indtast nøgleord (tryk på Enter efter hvert nøgleord)... + Dit brugernavn er typisk din e-mail adresse Tillad på rodniveau @@ -568,13 +569,13 @@ Berørte filer og foldere Flere informationer om at opsætte rettigheder for Umbraco her Du er nødt til at give ASP.NET 'modify' rettigheder på følgende filer/foldere - Dine rettighedsinstillinger er næsten perfekte!

Du kan køre Umbraco uden problemer, men du vil ikke være i stand til at installere pakker, som er anbefalet for at få fuldt udbytte af Umbraco.]]>
+ Dine rettighedsindstillinger er næsten perfekte!

Du kan køre Umbraco uden problemer, men du vil ikke være i stand til at installere pakker, som er anbefalet for at få fuldt udbytte af Umbraco.]]>
Hvorledes besluttes Klik her for at læse tekstversionen video tutorials om at opsætte folderrettigheder for Umbraco eller læs tekstversionen.]]> - Dine rettighedsinstillinger kan være et problem!

Du kan afvikle Umbraco uden problemer, men du vil ikke være i stand til at oprette foldere eller installere pakker, hvilket er anbefalet for at få fuldt udbytte af Umbraco.]]>
- Dine rettighedsinstillinger er ikke klar til Umbraco!

For at afvikle Umbraco er du nødt til at opdatere dine rettighedsinstillinger.]]>
- Dine rettighedsinstillinger er perfekte!

Du er nu parat til at afvikle Umbraco og installere pakker!]]>
+ Dine rettighedsindstillinger kan være et problem!

Du kan afvikle Umbraco uden problemer, men du vil ikke være i stand til at oprette foldere eller installere pakker, hvilket er anbefalet for at få fuldt udbytte af Umbraco.]]>
+ Dine rettighedsindstillinger er ikke klar til Umbraco!

For at afvikle Umbraco er du nødt til at opdatere dine rettighedsindstillinger.]]>
+ Dine rettighedsindstillinger er perfekte!

Du er nu parat til at afvikle Umbraco og installere pakker!]]>
Løser folder problem Følg dette link for mere information om udfordringer med ASP.NET og oprettelse af foldere Sætter folderrettigheder op @@ -586,7 +587,7 @@ Dette er vores liste over anbefalede moduler. Kryds dem af du ønsker at installere eller se den fulde liste af moduler ]]> Kun anbefalet for erfarne brugere Jeg ønsker at begynder med et simpelt website - "Runway" er et simpelt website som stiller nogle basale dokumenttyper og skabeloner til rådighed. Instaleringsprogrammet kan automatisk opsætte Runway for dig, men du kan nemt redigere, udvide eller fjerne det. Det er ikke nødvendigt og du kan sagtens bruge Umbraco uden. Men Runway tilbyder et fundament, som er baseret på 'Best Practices', som får dig igang hurtigere end nogensinde før. Hvis du vælger at installere Runway, kan du efter eget valg vælge de grundlæggende byggesten kaldet 'Runway Modules' til at forbedre dine Runway-sider.

Inkluderet med Runway:Home Page, Getting Started page, Installing Modules page.
Valgfri Moduler: Top Navigation, Sitemap, Contact, Gallery.

]]>
+ "Runway" er et simpelt website som stiller nogle basale dokumenttyper og skabeloner til rådighed. Installeringsprogrammet kan automatisk opsætte Runway for dig, men du kan nemt redigere, udvide eller fjerne det. Det er ikke nødvendigt og du kan sagtens bruge Umbraco uden. Men Runway tilbyder et fundament, som er baseret på 'Best Practices', som får dig igang hurtigere end nogensinde før. Hvis du vælger at installere Runway, kan du efter eget valg vælge de grundlæggende byggesten kaldet 'Runway Modules' til at forbedre dine Runway-sider.

Inkluderet med Runway:Home Page, Getting Started page, Installing Modules page.
Valgfri Moduler: Top Navigation, Sitemap, Contact, Gallery.

]]>
Hvad er Runway Skridt 1/5: Acceptér licens Skridt 2/5: Database-konfiguration @@ -703,7 +704,7 @@ Mange hilsner fra Umbraco robotten Pakke opbevaringsbase Bekræft af-installering Pakken blev fjernet - Pakken er på succefuld vis blevet fjernet + Pakken er på succesfuld vis blevet fjernet Afinstallér pakke @@ -784,7 +785,7 @@ Mange hilsner fra Umbraco robotten Tilføj række Tilføj indhold Slip indhold - Instillinger tilføjet + Indstillinger tilføjet Indholdet er ikke tilladt her Indholdet er tilladt her @@ -929,7 +930,7 @@ Mange hilsner fra Umbraco robotten Faneblad Titel på faneblad Faneblade - Master Dokument Type + Master Dokumenttype Opret matchende skabelon diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml index c451ccb597..b804fc0bc5 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/de.xml @@ -278,6 +278,7 @@ Durchsuchen ... Filtern ... Tippen, um Tags hinzuzufügen (nach jedem Tag die Eingabetaste drücken) ... + Der Benutzername ist normalerweise Ihre E-Mail-Adresse Auf oberster Ebene erlauben diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 87012194e3..3be1c1a0d7 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -339,6 +339,7 @@ Type to filter... Type to add tags (press enter after each tag)... Enter your email + Your username is usually your email Allow at root @@ -1257,6 +1258,8 @@ To manage your website, simply open the Umbraco back office and start adding con User Permissions User Types Users + Partial Views + Partial View Macro Files New update ready diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index c0904ae75c..2f2800c5d8 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -1443,4 +1443,7 @@ To manage your website, simply open the Umbraco back office and start adding con URL tracker has now been enabled. Error enabling the URL tracker, more information can be found in your log file. + + No Dictionary items to choose from + diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml index 9f9b5fd7ac..0c5bb2b120 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/es.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/es.xml @@ -277,6 +277,7 @@ Escribe un nombre... Escribe tu búsqueda... Escribe para filtrar resultados... + Tu nombre de usuario normalmente es tu e-mail Permitir en nodo raíz diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml index 7505f5e4ee..1fa59334f6 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/fr.xml @@ -329,6 +329,7 @@ Filtrer... Ajouter des tags (appuyer sur enter entre chaque tag)... Entrez votre email + Votre nom d'utilisateur est généralement votre adresse email diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml index 77ca781a59..955eff5ffd 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml @@ -284,6 +284,7 @@ Typ om te zoeken... Typ om te filteren... Typ om tags toe te voegen (druk op enter na elke tag)... + Jouw gebruikersnaam is meestal jouw email diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml index 1c4592adb0..4ec095f67a 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/ru.xml @@ -406,6 +406,9 @@ Показать метку Ширина и высота + + Нет доступных элементов словаря + Ваши данные сохранены, но для того, чтобы опубликовать этот документ, Вы должны сначала исправить следующие ошибки: Текущий провайдер ролей пользователей не поддерживает изменение пароля (необходимо свойству EnablePasswordRetrieval в файле web.config присвоить значение true) @@ -1008,6 +1011,7 @@ Укажите пароль Что искать... Укажите имя пользователя + Имя пользователя (часто это Ваш email-адрес) Остаться diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml index 66a1fab6f9..9e5eed4df6 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/sv.xml @@ -593,6 +593,7 @@ Skriv för att söka... Fyll i ditt lösenord Skriv för att lägga till taggar (och tryck enter efter varje tagg)... + Ditt användarnamn är vanligtvis din e-postadress Rollbaserat lösenordsskydd diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml index fcbf3c1ee7..196ba7b9aa 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/zh.xml @@ -1,7 +1,7 @@ - 孙柱梁 + 黄仁祥(wanddy@163.com) http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files @@ -24,8 +24,13 @@ 提醒 公众访问权限 发布 + 取消发布 重新加载节点 重新发布整站 + 恢复 + 为 %0%设置权限 + 选择移动目的地 + 到下列的树结构中 权限 回滚 提交至发布者 @@ -33,39 +38,40 @@ 排序 提交至发布者 翻译 - 取消发布 更新 + 默认值 禁止访问 添加域名 移除 错误的节点 + 域名错误 域名重复 - 域名 语言 + 域名 新域名 '%0%' 已创建 域名 '%0%' 已删除 域名 '%0%' 已使用 - - - https://www.example.com/、example.com/en、……使用 * 代表任意域名,
- 只需要设置语言部分即可。]]> -
域名 '%0%' 已更新 - 域名错误 编辑当前域名 + + https://www.example.com/、example.com/en、……使用 * 代表任意域名,
+ 只需要设置语言部分即可。]]>
继承 语言 - - 也可以从父节点继承。]]> - + + 也可以从父节点继承。]]> 域名 查看 + 清除选择 + 选择 + 选择当前目录 + 其它功能 粗体 取消段落缩进 插入表单字段 @@ -83,14 +89,17 @@ 插入宏 插入图片 编辑关联 + 返回列表 保存 保存并发布 保存并提交审核 + 保存列表视图 预览 因未设置模板无法预览 选择样式 显示样式 插入表格 + 生成模型 要更改所选节点的文档类型,先在列表中选择合适的文档类型。 @@ -113,21 +122,27 @@ 仅显示可作为替代的文档类型。 + 已发布 关于本页 别名 (图片的替代文本) 替代链接 点击编辑 创建者 + 原作者 + 更新者 创建时间 + 创建此文档的日期/时间 文档类型 编辑 过期于 该项发布之后有更改 该项没有发布 最近发布 - 媒体链接地址 + 没有要显示的项目 + 列表中没有要显示的项目。 媒体类型 + 媒体链接地址 会员组 角色 会员类型 @@ -136,26 +151,52 @@ 属性 该文档不可见,因为其上级 '%0%' 未发布。 该文档已发布,但是没有更新至缓存(内部错误) + Could not get the url + This document is published but its url would collide with content %0% 发布 发布状态 发布于 + 取消发布于 清空时间 排序完成 拖拽项目或单击列头即可排序,可以按住Shift多选。 统计 标题(可选) + Alternative text (optional) 类型 取消发布 最近编辑 + 编辑此文档的日期/时间 移除文件 链接到文档 会员组成员 非会员组成员 + 子项 + 目标 + 这将转换到服务器上的以下时间: + 这是什么意思?]]> + + + 点击上传 + 将文件放在此处.. + 链接到媒体 + 或单击此处选择文件 + 仅允许的文件类型为 + 最大文件大小为 + + + 创建新成员 + 所有成员 您想在哪里创建 %0% 创建在 选择类型和标题 + "文档类型" 下的 "设置" 部分中启用这些内容。]]> + "媒体类型" 下的 "设置" 部分中启用这些内容。]]> + 没有模板的文档类型 + 新建文件夹 + 新数据类型 浏览您的网站 @@ -167,38 +208,38 @@ 欢迎 - Stay - Discard changes - You have unsaved changes - Are you sure you want to navigate away from this page? - you have unsaved changes + 保持 + 丢弃更改 + 您有未保存的更改 + 确实要离开此页吗?-您有未保存的更改 - Done + 完成 - Deleted %0% item - Deleted %0% items - Deleted %0% out of %1% item - Deleted %0% out of %1% items + 已删除 %0% 项 + 已删除 %0% 项 + 已删除 %0% 项,共 %1% 项 + 已删除 %0% 项,共 %1% 项 - Published %0% item - Published %0% items - Published %0% out of %1% item - Published %0% out of %1% items + 已发布 %0% 项 + 已发布 %0% 项 + 已发布 %0% 项,共 %1% 项 + 已发布 %0% 项,共 %1% 项 - Unpublished %0% item - Unpublished %0% items - Unpublished %0% out of %1% item - Unpublished %0% out of %1% items + 已取消发布 %0% 项 + 已取消发布 %0% 项 + 已取消发布 %0% 项,共 %1% 项 + 已取消发布 %0% 项,共 %1% 项 - Moved %0% item - Moved %0% items - Moved %0% out of %1% item - Moved %0% out of %1% items + 已移动 %0% 项 + 已移动 %0% 项 + 已移动 %0% 项,共 %1% 项 + 已移动 %0% 项,共 %1% 项 - Copied %0% item - Copied %0% items - Copied %0% out of %1% item - Copied %0% out of %1% items + 已复制 %0% 项 + 已复制 %0% 项 + 已复制 %0% 项,共 %1% 项 + 已复制 %0% 项,共 %1% 项 锚点名称 @@ -240,24 +281,81 @@ 网站缓存将会刷新,所有已发布的内容将会更新。 表格列数 表格行数 - 设置一个占位符id 您可以在子模板中通过该ID来插入内容,引用格式: <asp:content />。]]> - 选择一个占位符id。]]> + 设置一个占位符id 您可以在子模板中通过该ID来插入内容, + 引用格式: <asp:content />。]]> + 选择一个 + 占位符id。]]> 点击图片查看完整大小 拾取项 查看缓存项 + 创建文件夹... + 与原始连接 + 包括后代 + 最友好的社区 + 链接到页面 + 在新窗口或选项卡中打开链接的文档 + 链接到媒体 + 选择媒体 + 选择图标 + 选择项 + 选择链接 + 选择宏 + 选择内容 + 选择成员 + 选择成员组 + 未找到图标 + 此宏没有参数 + 外部登录提供程序 + 异常详细信息 + 堆栈跟踪 + 内部异常 + 链接您的 + 取消链接您的 + 帐户 + 选择编辑器 - %0%’
您可以在左侧的“语言”中添加一种语言]]>
+ %0%’
您可以在左侧的“语言”中添加一种语言 + ]]>
语言名称 + 编辑字典项的键。 + + + + + + 输入您的用户名 + 输入您的密码 + 确认密码 + 命名 %0%... + 输入用户名... + 标签... + 输入说明... + 输入搜索关键字... + 输入过滤词... + 键入添加tags (在每个tag之后按 enter)... + 输入您的电子邮件 + 允许在根目录 + 只能在内容和媒体树的根级别创建具有选中的内容类型 允许子项节点类型 + 文档类型组合 创建 删除选项卡 描述 新建选项卡 选项卡 缩略图 + 启用列表视图 + 配置内容项以显示可排序和搜索的子项列表, 这些子项将不会显示在树中 + 当前列表视图 + 活动列表视图数据类型 + 创建自定义列表视图 + 删除自定义列表视图 添加预设值 @@ -286,10 +384,17 @@ %0% 格式不正确 + 从服务器收到错误 该文件类型已被管理员禁用 注意,尽管配置中允许CodeMirror,但是它在IE上不够稳定,所以无法在IE运行。 请为新的属性类型填写名称和别名! 权限有问题,访问指定文件或文件夹失败! + 加载Partial视图脚本时出错(文件: %0%) + 加载 userControl 时出错 '%0%' + 加载 customControl 时出错(程序集: %0%, 类型: '%1%') + 加载 MacroEngine 脚本时出错 (文件: %0%) + "解析 xslt 文件时出错: %0% + "读取 xslt 文件时出错: %0% 请输入标题 请选择类型 图片尺寸大于原始尺寸不会提高图片质量,您确定要把图片尺寸变大吗? @@ -302,13 +407,17 @@ 非合并单元格不能分离。 XSLT源码出错 XSLT未保存,因为包含错误。 + 此属性使用的数据类型存在配置错误, 请检查数据类型 关于 操作 + 操作 添加 别名 + 所有 您确定吗? + 返回 边框 取消 @@ -338,7 +447,6 @@ 邮箱 错误 查找文档 - 文件夹 帮助 图标 @@ -346,6 +454,7 @@ 内边距 插入 安装 + 无效 对齐 语言 布局 @@ -355,7 +464,9 @@ 退出 注销 + 必填项 移动 + 更多 名称 新的 下一步 @@ -375,6 +486,7 @@ 保持状态中 重命名 更新 + 必填 重试 权限 搜索 @@ -383,7 +495,7 @@ 在发送时预览 大小 排序 - Submit + 提交 类型 输入内容开始查找… @@ -398,9 +510,48 @@ 欢迎… - Reorder - I am done reordering + 文件夹 + 搜索结果 + 重新排序 + 我已结束排序 + 预览 + 更改密码 + + 列表视图 + 保存中... + 当前 + 嵌入 + 已选择 + + + 黑色 + 绿色 + 黄色 + 橙色 + 蓝色 + 红色 + + + + 添加选项卡 + 添加属性 + 添加编辑器 + 添加模板 + 添加子节点 + 添加子项 + + 编辑数据类型 + + 导航节 + + 快捷方式 + 显示快捷方式 + + 切换列表视图 + 切换允许作为根 + + 背景色 粗体 @@ -408,6 +559,7 @@ 字体 文本 + 页面 @@ -416,7 +568,9 @@ 无法保存web.config文件,请手工修改。 发现数据库 数据库配置 - 安装进行 %0% 数据库配置]]> + 安装进行 %0% 数据库配置 + ]]> 下一步继续。]]> 数据库未找到!请检查数据库连接串设置。

您可以自行编辑“web.config”文件,键名为 “UmbracoDbDSN”

@@ -426,8 +580,7 @@ ]]>
如有必要,请联系您的系统管理员。 - 如果您是本机安装,请使用管理员账号。 - ]]> + 如果您是本机安装,请使用管理员账号。]]>
点击更新来更新系统到 %0%

@@ -436,6 +589,7 @@

]]>
点击下一步继续。]]> + 下一步继续]]> 需要修改默认密码!]]> 默认账户已禁用或无权访问系统!

点击下一步继续。]]> @@ -443,7 +597,8 @@ 密码已更改 - 系统创建了一个默认用户(‘admin’)和默认密码(‘default’)。现在密码是随机的。 + 系统创建了一个默认用户(‘admin’)和默认密码(‘default’)。 + 现在密码是随机的。

该步骤建议您修改默认密码。 @@ -456,27 +611,24 @@ 此处查看更多信息 您需要对以下文件和文件夹授于ASP.NET用户修改权限 您当前的安全设置满足要求!

- 您可以毫无问题的运行系统,但您不能安装系统所推荐的扩展包的完整功能。 - ]]>
+ 您可以毫无问题的运行系统,但您不能安装系统所推荐的扩展包的完整功能。]]> 如何解决 点击阅读文字版 视频教程 ]]> 您当前的安全设置有问题!

- 您可以毫无问题的运行系统,但您不能新建文件夹、也不能安装系统所推荐的包的完整功能。 - ]]>
+ 您可以毫无问题的运行系统,但您不能新建文件夹、也不能安装系统所推荐的包的完整功能。 ]]> 您当前的安全设置不适合于系统!

- 您需要修改系统访问权限。 - ]]>
+ 您需要修改系统访问权限。]]> 您当前的权限设置正确!

- 您可以运行系统并安装其它扩展包! - ]]>
+ 您可以运行系统并安装其它扩展包!]]> 解决文件夹问题 点此查看ASP.NET和创建文件夹的问题解决方案 设置文件夹权限 我要从头开始 - Runway: Home page, Getting Started page, Installing Modules page.
- 可选模块: Top Navigation, Sitemap, Contact, Gallery. + Runway: 主页, 开始页, 安装模块页.
+ 可选模块: 顶部导航, 站点地图, 联系我们, 图库.
]]>
“Runway”是什么? @@ -515,11 +668,12 @@ 更多的帮助信息 从社区获取帮助]]> 系统 %0% 安装完毕 - /web.config file 的 AppSetting 键 UmbracoConfigurationStatus'%0%'。]]> + /web.config file 的 AppSetting 键 + UmbracoConfigurationStatus'%0%'。]]> 立即开始请点“运行系统”
如果您是新手, 您可以得到相当丰富的学习资源。]]>
运行系统 -管理您的网站, 运行后台添加内容,也可以添加模板和功能。 - ]]> +管理您的网站, 运行后台添加内容, +也可以添加模板和功能。]]> 无法连接到数据库。 系统版本 3 系统版本 4 @@ -537,8 +691,28 @@ 已更新,继续工作。 - © 2001 - %0%

]]>
- 欢迎使用Umbraco,在下方输入用户名和密码 + 星期一快乐 + 星期二快乐 + 星期三快乐 + 星期四快乐 + 星期五快乐 + 星期六快乐 + 星期天快乐 + 在下方登录 + 登录 + 会话超时 + © 2001 - %0%
Umbraco.com

]]>
+ 忘记密码? + 电子邮件将发送到地址指定的链接, 以重置您的密码 + 如果电子邮件与我们的记录相符, 则将发送带有密码重置指令的邮件 + 返回登录表单 + 请提供新密码 + 您的密码已更新 + 您单击的链接无效或已过期 + Umbraco: 重置密码 + + 您的用户名登录到 Umbraco 后台是: %0%

点击 这里 重置密码,或复制链接粘贴到您的浏览器访问:

%1%

]]> +
仪表板 @@ -564,37 +738,43 @@ %0%:

-

您好!这是一封自动发送的邮件,告诉您任务'%1%'已在'%2%'被用户'%3%'执行

- -

+

您好!这是一封自动发送的邮件,告诉您任务'%1%' + 已在'%2%' + 被用户'%3%'执行 +

+ +

更新概况:

- - %6% -
-

+ + %6% +
+

-
-
+

祝您愉快!

该信息由系统自动发送 -

- ]]> +

]]> 在 %2%,[%0%] 关于 %1% 的通告已执行。 通知 @@ -610,8 +790,7 @@ 名称 扩展包不含任何项
- 点击下面的“卸载”,您可以安全的删除。 - ]]>
+ 点击下面的“卸载”,您可以安全的删除。]]> 无可用更新 选项 说明 @@ -621,15 +800,24 @@ 扩展包卸载成功 卸载 - 注意:卸载包将导致所有依赖该包的东西失效,请确认。 - ]]> + 注意: + 卸载包将导致所有依赖该包的东西失效,请确认。 ]]> 从程序库下载更新 更新扩展包 更新说明 - 扩展包有可用的更新,您可以从程序库网站更新。 + 此软件包有一个可用的升级。您可以直接从 Umbraco 软件包存储库下载。 版本 版本历史 访问扩展包网站 + 已安装软件包 + 此软件包无法安装, 它需要一个最小的 Umbraco 版本的%0% + 卸载中... + 下载中... + 导入中... + 安装中... + 重启中, 请稍候... + 所有完成后, 您的浏览器将立即刷新, 请稍候... + 请单击 "完成" 以完成安装和重新加载页面。 带格式粘贴(不推荐) @@ -656,16 +844,23 @@ 如果您只希望提供一个用户名和密码就能访问 - - - - - + - + + + + + 包含未发布的子项 正在发布,请稍候… %0% 中的 %1% 页面已发布… @@ -673,20 +868,23 @@ %0% 及其子项已发布 发布 %0% 及其子项 确定 发布 %0%

-要发布当前页和所有子页,请选中 全部发布 发布所有子页。 - ]]>
+ 要发布当前页和所有子页,请选中 全部发布 发布所有子页。 + ]]> + + + 您没有配置任何认可的颜色 - - - - - - - - - - + 输入外部链接 + 选择内部页面 + 标题 + 链接 + 新窗口 + 输入新标题 + 输入链接 + + + Reset 当前版本 @@ -701,9 +899,9 @@ 编辑脚本 - Concierge + 礼宾 内容 - Courier + 导游 开发 Umbraco配置向导 媒体 @@ -713,11 +911,17 @@ 统计 翻译 用户 + 帮助 + 窗体 + 统计 + + + 转到 + 帮助主题 + 视频章节 + 最佳 Umbraco 视频教程 - 作为主控文档类型. 主控文档类型的标签只能在主控文档类型里修改。 - 主控文档类型激活 - 该文档类型使用 默认模板 字典键 要导入文档类型,请点击“浏览”按钮,再点击“导入”,然后在您电脑上查找 ".udt"文件导入(下一页中需要您再次确认) @@ -725,20 +929,33 @@ 节点类型 类型 样式表 + 脚本 样式表属性 选项卡 选项卡标题 选项卡 + 主控文档类型激活 + 该文档类型使用 + 作为主控文档类型. 主控文档类型的标签只能在主控文档类型里修改。 没有字段设置在该标签页 + 主控文档类型 + 创建匹配模板 + 添加图标 - Sort order - Creation date + 排序次序 + 创建日期 排序完成。 上下拖拽项目或单击列头进行排序
请不要关闭窗口]]>
+ 验证 + 在保存项之前必须修复验证错误 + 失败 + 用户权限不足, 无法完成操作 + 取消 + 操作被第三方插件取消。 发布因为第三方插件取消 属性类型已存在 属性类型已创建 @@ -748,7 +965,6 @@ 选项卡已创建 选项卡已删除 id为%0%的选项卡已删除 - 内容已取消发布 样式表未保存 样式表已保存 样式表保存,无错误。 @@ -775,6 +991,8 @@ 文件保存 文件保存,无错误。 语言已保存 + 已保存媒体类型 + 已保存成员类型 Python脚本未保存 Python脚本因为错误未能保存 Python已保存 @@ -788,10 +1006,16 @@ XSLT无法保存,请检查权限。 XSLT已保存 XSLT无错误 + 未发布内容 片段视图已保存 片段视图保存,无错误。 片段视图未保存 片段视图因为错误未能保存 + 已保存脚本视图 + 脚本视图保存时没有发生任何错误! + 未保存脚本视图 + 保存文件时出错。 + 保存文件时出错。 使用CSS语法,如:h1、.redHeader、.blueTex。 @@ -813,44 +1037,111 @@ 模板 - Choose type of content - Choose a layout - Add a row - Add content - Drop content - Settings applied + 选择内容类别 + 选择一项布局 + 添加一行 + 添加内容 + 丢弃内容 + 设置已应用 - This content is not allowed here - This content is allowed here + 此处不允许有该内容 + 此处允许有该内容 - Click to embed - Click to insert image - Image caption... - Write here... + 点击嵌入 + 点击添加图片 + 图片说明... + 在这里输入... - Grid Layouts - Layouts are the overall work area for the grid editor, usually you only need one or two different layouts - Add Grid Layout - Adjust the layout by setting column widths and adding additional sections - Row configurations - Rows are predefined cells arranged horizontally - Add row configuration - Adjust the row by setting cell widths and adding additional cells + 网格布局 + 布局是网格编辑器的整体工作区域, 通常只需要一个或两个不同的布局 + 添加网络布局 + 通过设置列宽并添加其他节来调整版式 + 行配置 + 行是水平排列的预定义单元格 + 添加行配置 + 通过设置单元格宽度和添加其他单元格来调整行 - Columns - Total combined number of columns in the grid layout + + 网格布局中的总和列数 - Settings - Configure what settings editors can change + 设置 + 配置编辑器可以更改的设置 - Styles - Configure what styling editors can change + 样式 + 配置编辑器可以更改的样式 - Settings will only save if the entered json configuration is valid + 输入的 json 配置有效, 设置才可保存 - Allow all editors - Allow all row configurations + 允许所有的编辑器 + 允许所有行配置 + 设置为默认值 + 选择附加 + 选择默认值 + 已增加 + + + + 组合 + 您没有添加任何选项卡 + 添加新选项卡 + 添加其他选项卡 + 继承自 + 添加属性 + 必需的标签 + + 启用列表视图 + 配置内容项以显示其子项的可排序和搜索列表, 这些子项将不会显示在树中 + + 允许的模板 + 选择允许在该类型的内容上使用哪些模板编辑器 + + 允许作为根 + 允许编辑器在内容树的根目录中创建此类型的内容 + 是 - 允许根中的此类型的内容 + + 允许的子节点类型 + 允许在该类型的内容下方创建指定类型的内容 + + 选择子节点 + + 从现有文档类型继承选项卡和属性。如果存在同名的选项卡, 则新选项卡将添加到当前文档类型或合并。 + 此内容类型在组合中使用, 因此不能自行组成。 + 没有可供组合使用的内容类型。 + + 可用编辑器 + 重用 + 编辑器设置 + + 配置 + + 是,删除 + + 被移动到下方 + 被复制到下面 + 选择要移动的文件夹 + 选择要复制的文件夹 + 在下面的树结构中 + + 所有文档类型 + 所有文档 + 所有媒体项目 + + 使用此文档类型将被永久删除, 请确认您还要删除这些文件。 + 使用此媒体类型将被永久删除, 请确认您也要删除这些。 + 使用此成员类型将被永久删除, 请确认您想要删除这些 + + 和所有使用此类型的文档 + 和所有使用此类型的媒体项目 + 和使用此类型的所有成员 + + 使用此编辑器将用新设置更新 + + 成员可编辑 + 显示成员配置文件 + + + 替代字段 替代文本 @@ -902,9 +1193,13 @@ 转到 http://%3%/translation/details.aspx?id=%4% 进行编辑 - 或登录http://%3%查看任务 + 或登录下列网址查看翻译任务 + http://%3% - 祝好运!]]> + Have a nice day! + + 来自Umbraco 机器人的祝福 + ]]> [%0%]翻译任务:%1% 没有翻译员,请创建翻译员角色的用户。 您创建的任务 @@ -913,6 +1208,7 @@ 关闭翻译任务,请返回详细视图点击“关闭”按钮。 ]]> 页面'%0%'已经发送给翻译 + 请选择内容应翻译成的语言 发送页面'%0%'以便翻译 分配者 任务开启 @@ -943,6 +1239,7 @@ 角色 会员类型 文档类型 + 关系类型 扩展包 扩展包 Python文件 @@ -955,8 +1252,9 @@ 模板 XSLT文件 用户权限 - 用户类型 Users + 分部视图 + 分部视图宏文件 有可用更新 @@ -968,8 +1266,9 @@ 管理员 分类字段 更改密码 - 要改变密码,请在框中输入新密码,然后单击“更改密码”。 + 更改密码 确认新密码 + 要改变密码,请在框中输入新密码,然后单击“更改密码”。 内容频道 描述字段 禁用用户 @@ -980,16 +1279,16 @@ 登录 默认打开媒体项 区域 - 更改密码 禁用后台管理界面 + 旧密码 密码 重设密码 您的密码已更改! 重输密码 - 当前密码 输入新密码 - 密码错误 新密码不能为空! + 当前密码 + 密码错误 新密码和重输入的密码不一致,请重试! 重输的密码和原密码不一致! 替换子项权限设置 @@ -1002,5 +1301,138 @@ 用户类型 用户类型 撰稿人 + 翻译人 + 更改 + 你的资料 + 你最近的历史信息 + 会话过期于 + + + 验证 + 验证为电子邮件 + 验证为数字 + 验证为 url + ...或输入自定义验证 + 字段是强制性的 + + + + Value is set to the recommended value: '%0%'. + Value was set to '%1%' for XPath '%2%' in configuration file '%3%'. + Expected value '%1%' for '%2%' in configuration file '%3%', but found '%0%'. + Found unexpected value '%0%' for '%2%' in configuration file '%3%'. + + + Custom errors are set to '%0%'. + Custom errors are currently set to '%0%'. It is recommended to set this to '%1%' before go live. + Custom errors successfully set to '%0%'. + + MacroErrors are set to '%0%'. + MacroErrors are set to '%0%' which will prevent some or all pages in your site from loading completely if there are any errors in macros. Rectifying this will set the value to '%1%'. + MacroErrors are now set to '%0%'. + + + Try Skip IIS Custom Errors is set to '%0%' and you're using IIS version '%1%'. + Try Skip IIS Custom Errors is currently '%0%'. It is recommended to set this to '%1%' for your IIS version (%2%). + Try Skip IIS Custom Errors successfully set to '%0%'. + + + File does not exist: '%0%'. + '%0%' in config file '%1%'.]]> + There was an error, check log for full error: %0%. + + Members - Total XML: %0%, Total: %1%, Total invalid: %2% + Media - Total XML: %0%, Total: %1%, Total invalid: %2% + Content - Total XML: %0%, Total published: %1%, Total invalid: %2% + + Your site certificate was marked as valid. + Certificate validation error: '%0%' + Error pinging the URL %0% - '%1%' + You are currently %0% viewing the site using the HTTPS scheme. + The appSetting 'umbracoUseSSL' is set to 'false' in your web.config file. Once you access this site using the HTTPS scheme, that should be set to 'true'. + The appSetting 'umbracoUseSSL' is set to '%0%' in your web.config file, your cookies are %1% marked as secure. + Could not update the 'umbracoUseSSL' setting in your web.config file. Error: %0% + + + Enable HTTPS + Sets umbracoSSL setting to true in the appSettings of the web.config file. + The appSetting 'umbracoUseSSL' is now set to 'true' in your web.config file, your cookies will be marked as secure. + + Fix + Cannot fix a check with a value comparison type of 'ShouldNotEqual'. + Cannot fix a check with a value comparison type of 'ShouldEqual' with a provided value. + Value to fix check not provided. + + Debug compilation mode is disabled. + Debug compilation mode is currently enabled. It is recommended to disable this setting before go live. + Debug compilation mode successfully disabled. + + Trace mode is disabled. + Trace mode is currently enabled. It is recommended to disable this setting before go live. + Trace mode successfully disabled. + + All folders have the correct permissions set. + + %0%.]]> + %0%. If they aren't being written to no action need be taken.]]> + + All files have the correct permissions set. + + %0%.]]> + %0%. If they aren't being written to no action need be taken.]]> + + X-Frame-Options used to control whether a site can be IFRAMEd by another was found.]]> + X-Frame-Options used to control whether a site can be IFRAMEd by another was not found.]]> + Set Header in Config + Adds a value to the httpProtocol/customHeaders section of web.config to prevent the site being IFRAMEd by other websites. + A setting to create a header preventing IFRAMEing of the site by other websites has been added to your web.config file. + Could not update web.config file. Error: %0% + + + %0%.]]> + No headers revealing information about the website technology were found. + + In the Web.config file, system.net/mailsettings could not be found. + In the Web.config file system.net/mailsettings section, the host is not configured. + SMTP settings are configured correctly and the service is operating as expected. + The SMTP server configured with host '%0%' and port '%1%' could not be reached. Please check to ensure the SMTP settings in the Web.config file system.net/mailsettings are correct. + + %0%.]]> + %0%.]]> + + + 禁用 url 跟踪程序 + 启用 url 跟踪程序 + 原始网址 + 已重定向至 + 未进行重定向 + 当已发布的页重命名或移动时, 将自动对新页进行重定向。 + 删除 + 确实要删除 "%0%" 到 "%1%" 的重定向吗? + 重定向URL已删除。 + 删除重定向 url 时出错. + 是否确实要禁用 url 跟踪程序? + url 跟踪器现在已被禁用。 + 禁用 url 跟踪程序时出错, 可以在日志文件中找到更多信息。 + 现在已启用 url 跟踪程序。 + 启用 url 跟踪程序时出错, 可以在日志文件中找到更多信息。 diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/BrowseRepository.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/BrowseRepository.aspx deleted file mode 100644 index 076c767b01..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/BrowseRepository.aspx +++ /dev/null @@ -1,20 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../../masterpages/umbracoPage.Master" Title="Browse Repository" CodeBehind="BrowseRepository.aspx.cs" Inherits="umbraco.presentation.developer.packages.BrowseRepository" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/LoadNitros.ascx b/src/Umbraco.Web.UI/umbraco/developer/Packages/LoadNitros.ascx deleted file mode 100644 index d79cc6e881..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/LoadNitros.ascx +++ /dev/null @@ -1,32 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="LoadNitros.ascx.cs" Inherits="umbraco.presentation.developer.packages.LoadNitros" %> - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx deleted file mode 100644 index 059e0f727a..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx +++ /dev/null @@ -1,86 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="True" MasterPageFile="../../masterpages/umbracoPage.Master" Title="Install starter kit" CodeBehind="StarterKits.aspx.cs" Inherits="Umbraco.Web.UI.Umbraco.Developer.Packages.StarterKits" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - - - - - - - - - -

Available starter kits

-

You can choose from the following starter kits, each having specific functionality.

-
Please wait...
-
-
-
- -
-
- - -

Installation completed succesfully

-
- - -

We can not install starterkits when the install directory or package repository is not present.

-
- - -
- - -
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx.cs b/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx.cs deleted file mode 100644 index 2afd4394fe..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Web.UI.Install.Steps.Skinning; -using Umbraco.Web.UI.Pages; -using System.IO; -using umbraco.cms.businesslogic.packager; - -namespace Umbraco.Web.UI.Umbraco.Developer.Packages -{ - - - public partial class StarterKits : UmbracoEnsuredPage - { - private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; - - protected void Page_Load(object sender, EventArgs e) - { - //check if a starter kit is already isntalled - - var installed = InstalledPackage.GetAllInstalledPackages(); - - if (installed.Count == 0) - { - ShowStarterKits(); - return; - } - - var repo = global::umbraco.cms.businesslogic.packager.repositories.Repository.getByGuid(RepoGuid); - if (repo.HasConnection()) - { - try - { - var kits = repo.Webservice.StarterKits(); - var kitIds = kits.Select(x => x.RepoGuid).ToArray(); - - //if a starter kit is already installed show finish - if (installed.Any(x => kitIds.Contains(Guid.Parse(x.Data.PackageGuid)))) - { - StarterKitNotInstalled.Visible = false; - installationCompleted.Visible = true; - } - else - { - ShowStarterKits(); - } - } - catch (Exception ex) - { - Current.Logger.Error("Cannot connect to package repository", ex); - InstallationDirectoryNotAvailable.Visible = true; - StarterKitNotInstalled.Visible = false; - } - } - else - { - InstallationDirectoryNotAvailable.Visible = true; - StarterKitNotInstalled.Visible = false; - } - } - - private void ShowStarterKits() - { - if (Directory.Exists(Server.MapPath(GlobalSettings.Path.EnsureEndsWith('/') + "install/Legacy")) == false) - { - InstallationDirectoryNotAvailable.Visible = true; - StarterKitNotInstalled.Visible = false; - - return; - } - - - var starterkitsctrl = (LoadStarterKits)LoadControl(GlobalSettings.Path.EnsureEndsWith('/') + "install/Legacy/loadStarterKits.ascx"); - - ph_starterkits.Controls.Add(starterkitsctrl); - - StarterKitNotInstalled.Visible = true; - - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx.designer.cs b/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx.designer.cs deleted file mode 100644 index 105a8ff5df..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/StarterKits.aspx.designer.cs +++ /dev/null @@ -1,78 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Umbraco.Web.UI.Umbraco.Developer.Packages { - - - public partial class StarterKits { - - /// - /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// Panel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.UmbracoPanel Panel1; - - /// - /// fb control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Feedback fb; - - /// - /// StarterKitNotInstalled control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane StarterKitNotInstalled; - - /// - /// ph_starterkits control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder ph_starterkits; - - /// - /// installationCompleted control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane installationCompleted; - - /// - /// InstallationDirectoryNotAvailable control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane InstallationDirectoryNotAvailable; - } -} diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/SubmitPackage.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/SubmitPackage.aspx deleted file mode 100644 index 1a986594e3..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/SubmitPackage.aspx +++ /dev/null @@ -1,113 +0,0 @@ -<%@ Page Language="C#" Title="Submit package" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="SubmitPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.SubmitPackage" %> -<%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - -
- - -
-

- -

-
- - - - - -

Choose the repository you want to submit the package to

-
- - - -
- - - -
- - - -

Upload additional documentation for your package to help new users getting started with your package

-
- - - - - -
- - -
- -
-

By clicking "submit package" below you understand that your package will be submitted to a package repository and will in some cases be publicly available to download.

-

Please notice: only packages with complete read-me, author information and install information gets considered for inclusion.

-

The package administrators group reservers the right to decline packages based on lack of documentation, poorly written readme and missing author information

-
- -

-  <%= Services.TextService.Localize("or") %>  "><%= Services.TextService.Localize("cancel") %> -

-
- -
-
diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx index 87faed4e43..edd484c82e 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/Packages/editPackage.aspx @@ -39,7 +39,6 @@ - diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx b/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx deleted file mode 100644 index 22db3e58cf..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/installedPackage.aspx +++ /dev/null @@ -1,185 +0,0 @@ -<%@ Page Language="C#" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="installedPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.installedPackage" %> -<%@ Import Namespace="Umbraco.Core.Configuration" %> -<%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - - - - - - - - - - -

- <%= Services.TextService.Localize("packager/packageUpgradeText") %> -

-
- - -

- -

- -

- -

-
-
- - -
- - <%= Services.TextService.Localize("packager/packageNoItemsText") %> - -

- -

-
- -
- - - -

- <%= Services.TextService.Localize("packager/packageUninstallText") %> -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- Package uninstall in progress, please wait while the browser is reloaded... -
- - - - -
-
-
diff --git a/src/Umbraco.Web.UI/umbraco/developer/Packages/proxy.htm b/src/Umbraco.Web.UI/umbraco/developer/Packages/proxy.htm deleted file mode 100644 index 43aef0ab96..0000000000 --- a/src/Umbraco.Web.UI/umbraco/developer/Packages/proxy.htm +++ /dev/null @@ -1,67 +0,0 @@ - - - - Repo proxy - - - - - - - diff --git a/src/Umbraco.Web.UI/umbraco/translation/default.aspx b/src/Umbraco.Web.UI/umbraco/translation/default.aspx index 6a4be5cf5b..872e0481fa 100644 --- a/src/Umbraco.Web.UI/umbraco/translation/default.aspx +++ b/src/Umbraco.Web.UI/umbraco/translation/default.aspx @@ -16,7 +16,7 @@

- When you have completed the translation. Upload the edited XML file here. The related translation tasks will automaticly be closed when a file is uploaded. + When you have completed the translation. Upload the edited XML file here. The related translation tasks will automatically be closed when a file is uploaded.

diff --git a/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx b/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx index 815a420f88..75b5d6e66a 100644 --- a/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx +++ b/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx @@ -1,5 +1,5 @@ <%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../masterpages/umbracoPage.Master" CodeBehind="PermissionEditor.aspx.cs" Inherits="umbraco.cms.presentation.user.PermissionEditor" %> - +<%@ Import Namespace="Umbraco.Web" %> <%@ Register Src="../controls/Tree/TreeControl.ascx" TagName="TreeControl" TagPrefix="umbraco" %> <%@ Register Src="NodePermissions.ascx" TagName="NodePermissions" TagPrefix="user" %> <%@ Register TagPrefix="ui" Namespace="umbraco.uicontrols" Assembly="controls" %> @@ -27,7 +27,7 @@ - diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/BrowseRepository.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/BrowseRepository.aspx.cs deleted file mode 100644 index a161f09693..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/BrowseRepository.aspx.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using Umbraco.Core; -using Umbraco.Core.Services; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; -using Umbraco.Web; -using Umbraco.Web.UI.Pages; - -namespace umbraco.presentation.developer.packages { - public partial class BrowseRepository : UmbracoEnsuredPage { - - public BrowseRepository() - { - CurrentApp = Constants.Applications.Developer.ToString(); - - } - - protected void Page_Load(object sender, System.EventArgs e) { - - Exception ex = new Exception(); - if (!cms.businesslogic.packager.Settings.HasFileAccess(ref ex)) { - fb.Style.Add("margin-top", "7px"); - fb.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - fb.Text = "" + Services.TextService.Localize("errors/filePermissionsError") + ":
" + ex.Message; - } - - string category = Request.CleanForXss("category"); - string repoGuid = Request.CleanForXss("repoGuid"); - - var repo = cms.businesslogic.packager.repositories.Repository.getByGuid(repoGuid); - if (repo == null) - { - throw new InvalidOperationException("Could not find repository with id " + repoGuid); - } - - string url = repo.RepositoryUrl; - - Panel1.Text = "Browse repository: " + repo.Name; - - if (!string.IsNullOrEmpty(category)) - category = "&category=" + category; - - iframeGen.Text = - string.Format( - "", - url, repoGuid, category, Request.ServerVariables["SERVER_NAME"], - Request.ServerVariables["SERVER_PORT"], IOHelper.ResolveUrl(SystemDirectories.Umbraco), - IOHelper.ResolveUrl(SystemDirectories.Umbraco).Trim('/'), repoGuid, - UmbracoVersion.Current.Major, - UmbracoVersion.Current.Minor, - UmbracoVersion.Current.Build, - Environment.Version, - Umbraco.Core.SystemUtilities.GetCurrentTrustLevel()); - } - - - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/BrowseRepository.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/BrowseRepository.aspx.designer.cs deleted file mode 100644 index 1612a7daa0..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/BrowseRepository.aspx.designer.cs +++ /dev/null @@ -1,43 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:2.0.50727.3053 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.developer.packages { - - - public partial class BrowseRepository { - - /// - /// Panel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.UmbracoPanel Panel1; - - /// - /// fb control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Feedback fb; - - /// - /// iframeGen control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal iframeGen; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx deleted file mode 100644 index d79cc6e881..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx +++ /dev/null @@ -1,32 +0,0 @@ -<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="LoadNitros.ascx.cs" Inherits="umbraco.presentation.developer.packages.LoadNitros" %> - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx.cs deleted file mode 100644 index 6e7f432e2b..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System.IO; -using System; -using System.Data; -using System.Drawing; -using System.Web; -using System.Web.UI.WebControls; -using System.Web.UI.HtmlControls; -using System.Collections; -using System.Web.UI; -using System.Web.UI.WebControls.WebParts; -using System.Collections.Generic; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; -using umbraco.BusinessLogic; -using Umbraco.Web; - -namespace umbraco.presentation.developer.packages { - public partial class LoadNitros : System.Web.UI.UserControl { - - private List _nitroList = new List(); - private List _selectedNitros = new List(); - - protected void Page_Load(object sender, EventArgs e) { } - - public void installNitros(object sender, EventArgs e) { - - string repoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; //Hardcoded official package repo key. - - var p = new cms.businesslogic.packager.Installer(Umbraco.Web.UmbracoContext.Current.Security.CurrentUser.Id); - var repo = cms.businesslogic.packager.repositories.Repository.getByGuid(repoGuid); - - if (repo == null) - { - throw new InvalidOperationException("Could not find repository with id " + repoGuid); - } - - foreach (CheckBox cb in _nitroList) { - if (cb.Checked) { - if (!_selectedNitros.Contains(cb.ID)) - _selectedNitros.Add(cb.ID); - } - } - - foreach (string guid in _selectedNitros) { - - string tempFile = p.Import(repo.fetch(guid)); - p.LoadConfig(tempFile); - - int pId = p.CreateManifest(tempFile, guid, repoGuid); - - //and then copy over the files. This will take some time if it contains .dlls that will reboot the system.. - p.InstallFiles(pId, tempFile); - - //finally install the businesslogic - p.InstallBusinessLogic(pId, tempFile); - - //cleanup.. - p.InstallCleanUp(pId, tempFile); - - } - - Current.ApplicationCache.RuntimeCache.ClearAllCache(); - Current.ApplicationCache.IsolatedRuntimeCache.ClearAllCaches(); - - // library.RefreshContent is obsolete, would need to RefreshAllFacade, - // but it should be managed automatically by services and caches! - //DistributedCache.Instance.RefreshAllFacade(); - - loadNitros.Visible = false; - - RaiseBubbleEvent(new object(), new EventArgs()); - } - - protected void onCategoryDataBound(object sender, RepeaterItemEventArgs e) { - - if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item) { - - cms.businesslogic.packager.repositories.Category cat = (cms.businesslogic.packager.repositories.Category)e.Item.DataItem; - Literal _name = (Literal)e.Item.FindControl("lit_name"); - Literal _desc = (Literal)e.Item.FindControl("lit_desc"); - PlaceHolder _nitros = (PlaceHolder)e.Item.FindControl("ph_nitroHolder"); - - _name.Text = cat.Text; - _desc.Text = cat.Description; - - e.Item.Visible = false; - - foreach (cms.businesslogic.packager.repositories.Package nitro in cat.Packages) { - bool installed = cms.businesslogic.packager.InstalledPackage.isPackageInstalled(nitro.RepoGuid.ToString()); - int localPackageID = 0; - - if (installed) - localPackageID = cms.businesslogic.packager.InstalledPackage.GetByGuid(nitro.RepoGuid.ToString()).Data.Id; - - CheckBox cb_nitro = new CheckBox(); - cb_nitro.ID = nitro.RepoGuid.ToString(); - cb_nitro.Enabled = !installed; - - cb_nitro.CssClass = "nitroCB"; - - cb_nitro.Text = "

" + nitro.Text; - - if (installed) { - cb_nitro.CssClass = "nitroCB installed"; - cb_nitro.Text += "Already installed"; - } - - cb_nitro.Text += "

" + nitro.Description + "
"; - - if (!string.IsNullOrEmpty(nitro.Demo)) { - cb_nitro.Text += "Demonstration  "; - } - - if (!string.IsNullOrEmpty(nitro.Documentation)) { - cb_nitro.Text += "Documentation  "; - } - - cb_nitro.Text += "

"; - - _nitros.Controls.Add(cb_nitro); - _nitroList.Add(cb_nitro); - - e.Item.Visible = true; - - if (nitro.EditorsPick) { - - CheckBox cb_Recnitro = new CheckBox(); - cb_Recnitro.ID = nitro.RepoGuid.ToString(); - cb_Recnitro.CssClass = "nitroCB"; - cb_Recnitro.Enabled = !installed; - - cb_Recnitro.Text = "

" + nitro.Text; - - if (installed) { - cb_Recnitro.CssClass = "nitroCB installed"; - cb_Recnitro.Text += "Already installed"; - } - - cb_Recnitro.Text += "

" + nitro.Description + "
"; - - if (!string.IsNullOrEmpty(nitro.Demo)) { - cb_Recnitro.Text += "Demonstration  "; - } - - if (!string.IsNullOrEmpty(nitro.Documentation)) { - cb_Recnitro.Text += "Documentation  "; - } - - cb_Recnitro.Text += "

"; - - - _nitroList.Add(cb_Recnitro); - ph_recommendedHolder.Controls.Add(cb_Recnitro); - - } - } - - } - } - - - protected override void OnInit(EventArgs e) { - - base.OnInit(e); - - string repoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66"; - var repo = cms.businesslogic.packager.repositories.Repository.getByGuid(repoGuid); - - if (repo == null) - { - throw new InvalidOperationException("Could not find repository with id " + repoGuid); - } - - var fb = new global::umbraco.uicontrols.Feedback(); - fb.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - fb.Text = "No connection to repository. Modules could not be fetched from the repository as there was no connection to: '" + repo.RepositoryUrl + "'"; - - - if (repo.HasConnection()) - { - try - { - - rep_nitros.DataSource = repo.Webservice.NitrosCategorizedByVersion(cms.businesslogic.packager.repositories.Version.Version41); - - rep_nitros.DataBind(); - } - catch (Exception ex) - { - Current.Logger.Error("An error occurred", ex); - - loadNitros.Controls.Clear(); - loadNitros.Controls.Add(fb); - //nitroList.Visible = false; - //lt_status.Text = "

Nitros could not be fetched from the repository. Please check your internet connection

You can always install Nitros later in the packages section

" + ex.ToString() + "

"; - } - } - else - { - loadNitros.Controls.Clear(); - loadNitros.Controls.Add(fb); - } - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx.designer.cs deleted file mode 100644 index 50aca0d082..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/LoadNitros.ascx.designer.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:2.0.50727.3053 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.developer.packages { - - - public partial class LoadNitros { - - /// - /// loadNitros control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel loadNitros; - - /// - /// ph_recommendedHolder control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder ph_recommendedHolder; - - /// - /// rep_nitros control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater rep_nitros; - - /// - /// bt_install control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_install; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx deleted file mode 100644 index 1a986594e3..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx +++ /dev/null @@ -1,113 +0,0 @@ -<%@ Page Language="C#" Title="Submit package" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="SubmitPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.SubmitPackage" %> -<%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - -
- - -
-

- -

-
- - - - - -

Choose the repository you want to submit the package to

-
- - - -
- - - -
- - - -

Upload additional documentation for your package to help new users getting started with your package

-
- - - - - -
- - -
- -
-

By clicking "submit package" below you understand that your package will be submitted to a package repository and will in some cases be publicly available to download.

-

Please notice: only packages with complete read-me, author information and install information gets considered for inclusion.

-

The package administrators group reservers the right to decline packages based on lack of documentation, poorly written readme and missing author information

-
- -

-  <%= Services.TextService.Localize("or") %>  "><%= Services.TextService.Localize("cancel") %> -

-
- -
-
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx.cs deleted file mode 100644 index 3e5bfaa247..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Data; -using System.Configuration; -using System.Collections; -using System.Collections.Generic; - -using System.Web; -using System.Web.Security; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Web.UI.WebControls.WebParts; -using System.Web.UI.HtmlControls; -using Umbraco.Core; -using Umbraco.Web; -using Umbraco.Web.UI.Pages; - -namespace umbraco.presentation.developer.packages { - public partial class SubmitPackage : UmbracoEnsuredPage { - - public SubmitPackage() - { - CurrentApp = Constants.Applications.Developer.ToString(); - - } - private cms.businesslogic.packager.PackageInstance pack; - private cms.businesslogic.packager.CreatedPackage createdPackage; - - protected void Page_Load(object sender, EventArgs e) { - - if(!String.IsNullOrEmpty(Request.GetItemAsString("id"))){ - - if (!IsPostBack) { - dd_repositories.Items.Clear(); - - dd_repositories.Items.Add(new ListItem("Choose a repository...", "")); - - List repos = cms.businesslogic.packager.repositories.Repository.getAll(); - - if (repos.Count == 1) { - ListItem li = new ListItem(repos[0].Name, repos[0].Guid); - li.Selected = true; - - dd_repositories.Items.Add(li); - - pl_repoChoose.Visible = false; - pl_repoLogin.Style.Clear(); - - privateRepoHelp.Visible = false; - publicRepoHelp.Style.Clear(); - - } else if (repos.Count == 0) { - Response.Redirect("editpackage.aspx?id=" + Request.GetItemAsString("id")); - } else { - - foreach (cms.businesslogic.packager.repositories.Repository repo in repos) { - dd_repositories.Items.Add(new ListItem(repo.Name, repo.Guid)); - } - - dd_repositories.Items[0].Selected = true; - - dd_repositories.Attributes.Add("onChange", "onRepoChange()"); - - } - } - - createdPackage = cms.businesslogic.packager.CreatedPackage.GetById(int.Parse(Request.GetItemAsString("id"))); - pack = createdPackage.Data; - - if (pack.Url != "") { - Panel1.Text = "Submit '" + pack.Name + "' to a repository"; - } - } - } - - protected void submitPackage(object sender, EventArgs e) { - - Page.Validate(); - string feedback = ""; - - if (Page.IsValid) { - - try { - var repo = cms.businesslogic.packager.repositories.Repository.getByGuid(dd_repositories.SelectedValue); - - if (repo == null) - { - throw new InvalidOperationException("Could not find repository with id " + dd_repositories.SelectedValue); - } - - var memberKey = repo.Webservice.authenticate(tb_email.Text, library.md5(tb_password.Text)); - - byte[] doc = new byte[0]; - - if (fu_doc.HasFile) - doc = fu_doc.FileBytes; - - - - if (memberKey != "") { - - string result = repo.SubmitPackage(memberKey, pack, doc).ToString().ToLower(); - - switch (result) { - case "complete": - feedback = "Your package has been submitted successfully. It will be reviewed by the package repository administrator before it's publicly available"; - fb_feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success; - break; - case "error": - feedback = "There was a general error submitting your package to the repository. This can be due to general communitations error or too much traffic. Please try again later"; - fb_feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - break; - case "exists": - feedback = "This package has already been submitted to the repository. You cannot submit it again. If you have updates for a package, you should contact the repositor administrator to submit an update"; - fb_feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - break; - case "noaccess": - feedback = "Authentication failed, You do not have access to this repository. Contact your package repository administrator"; - fb_feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - break; - default: - break; - } - - if (result == "complete") { - Pane1.Visible = false; - Pane2.Visible = false; - submitControls.Visible = false; - feedbackControls.Visible = true; - } else { - Pane1.Visible = true; - Pane2.Visible = true; - submitControls.Visible = true; - feedbackControls.Visible = false; - } - - } else { - feedback = "Authentication failed, You do not have access to this repository. Contact your package repository administrator"; - fb_feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - } - } catch { - feedback = "Authentication failed, or the repository is currently off-line. Contact your package repository administrator"; - fb_feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.error; - } - - fb_feedback.Text = feedback; - } - - - - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx.designer.cs deleted file mode 100644 index 7eb884632a..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/SubmitPackage.aspx.designer.cs +++ /dev/null @@ -1,214 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:2.0.50727.3053 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.developer.packages { - - - public partial class SubmitPackage { - - /// - /// Panel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.UmbracoPanel Panel1; - - /// - /// fb_feedback control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Feedback fb_feedback; - - /// - /// feedbackControls control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder feedbackControls; - - /// - /// Pane2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane Pane2; - - /// - /// pl_repoChoose control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel pl_repoChoose; - - /// - /// dd_repositories control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList dd_repositories; - - /// - /// pl_repoLogin control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel pl_repoLogin; - - /// - /// PropertyPanel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel PropertyPanel1; - - /// - /// publicRepoHelp control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlGenericControl publicRepoHelp; - - /// - /// privateRepoHelp control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlGenericControl privateRepoHelp; - - /// - /// PropertyPanel2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel PropertyPanel2; - - /// - /// tb_email control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox tb_email; - - /// - /// RequiredFieldValidator1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1; - - /// - /// PropertyPanel3 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel PropertyPanel3; - - /// - /// tb_password control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox tb_password; - - /// - /// Pane1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane Pane1; - - /// - /// PropertyPanel4 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel PropertyPanel4; - - /// - /// PropertyPanel5 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel PropertyPanel5; - - /// - /// fu_doc control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.FileUpload fu_doc; - - /// - /// doc_regex control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RegularExpressionValidator doc_regex; - - /// - /// submitControls control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder submitControls; - - /// - /// bt_submit control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_submit; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx index bd34c32478..b66388d3a0 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx @@ -36,7 +36,6 @@ ControlToValidate="packageVersion">* - @@ -118,7 +117,7 @@ Remember: .xslt and .ascx files for your macros - will be added automaticly, but you will still need to add assemblies, + will be added automatically, but you will still need to add assemblies, images and script files manually to the list below. diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs index d4eae1fbda..1541955977 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.cs @@ -52,16 +52,10 @@ namespace umbraco.presentation.developer.packages cp = new ContentPicker(); content.Controls.Add(cp); - - bt_submitButton.Attributes.Add("onClick", "window.location = 'submitpackage.aspx?id=" + pack.Id.ToString() + "'; return false;"); - + if (string.IsNullOrEmpty(pack.PackagePath) == false) { - packageUmbFile.Text = "   Download"; - - if (cms.businesslogic.packager.repositories.Repository.getAll().Count > 0) - bt_submitButton.Visible = true; - + packageUmbFile.Text = "   Download"; } else { diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs index a4c21695a7..dfd3eaa5d7 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/editPackage.aspx.designer.cs @@ -47,6 +47,7 @@ namespace umbraco.presentation.developer.packages { protected global::System.Web.UI.WebControls.RegularExpressionValidator VersionValidator; protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator7; + /// /// packageName control. /// @@ -128,15 +129,6 @@ namespace umbraco.presentation.developer.packages { /// protected global::umbraco.uicontrols.PropertyPanel pp_file; - /// - /// bt_submitButton control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_submitButton; - /// /// packageUmbFile control. /// diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx deleted file mode 100644 index c3c46f3611..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx +++ /dev/null @@ -1,180 +0,0 @@ -<%@ Page Language="C#" MasterPageFile="../../masterpages/umbracoPage.Master" AutoEventWireup="true" CodeBehind="installedPackage.aspx.cs" Inherits="umbraco.presentation.developer.packages.installedPackage" %> -<%@ Register TagPrefix="cc2" Namespace="umbraco.uicontrols" Assembly="controls" %> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - - - - - - - - - - -

- <%= Services.TextService.Localize("packager/packageUpgradeText") %> -

-
- - -

- -

- -

- -

-
-
- - -
- - <%= Services.TextService.Localize("packager/packageNoItemsText") %> - -

- -

-
- -
- - - -

- <%= Services.TextService.Localize("packager/packageUninstallText") %> -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - -

-
-
- - - -
- Please wait while the browser is reloaded... -
- - - - -
- -
-
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs deleted file mode 100644 index 141348ac6f..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.cs +++ /dev/null @@ -1,630 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Web.UI.WebControls; -using Umbraco.Core.IO; -using Umbraco.Core; -using Umbraco.Core.Services; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using umbraco.cms.businesslogic.web; -using System.Xml; -using umbraco.cms.presentation.Trees; -using Umbraco.Web; -using Umbraco.Web.UI.Pages; -using BizLogicAction = Umbraco.Web._Legacy.Actions.Action; -using Macro = umbraco.cms.businesslogic.macro.Macro; -using Template = umbraco.cms.businesslogic.template.Template; - -namespace umbraco.presentation.developer.packages -{ - public partial class installedPackage : UmbracoEnsuredPage - { - public installedPackage() - { - CurrentApp = Constants.Applications.Developer.ToString(); - } - - private cms.businesslogic.packager.InstalledPackage _pack; - private cms.businesslogic.packager.repositories.Repository _repo = new cms.businesslogic.packager.repositories.Repository(); - - protected void Page_Load(object sender, EventArgs e) - { - - if (Request.QueryString["id"] != null) - { - _pack = cms.businesslogic.packager.InstalledPackage.GetById(int.Parse(Request.QueryString["id"])); - - lt_packagename.Text = _pack.Data.Name; - lt_packageVersion.Text = _pack.Data.Version; - lt_packageAuthor.Text = _pack.Data.Author; - lt_readme.Text = library.ReplaceLineBreaks( _pack.Data.Readme ); - - bt_confirmUninstall.Attributes.Add("onClick", "jQuery('#buttons').hide(); jQuery('#loadingbar').show();; return true;"); - - - if (!Page.IsPostBack) - { - //temp list to contain failing items... - var tempList = new List(); - - foreach (var str in _pack.Data.Documenttypes) - { - var tId = 0; - if (int.TryParse(str, out tId)) - { - try - { - var dc = new DocumentType(tId); - var li = new ListItem(dc.Text, dc.Id.ToString()); - li.Selected = true; - documentTypes.Items.Add(li); - } - catch - { - tempList.Add(str); - } - } - } - //removing failing documentTypes items from the uninstall manifest - SyncLists(_pack.Data.Documenttypes, tempList); - - - foreach (var str in _pack.Data.Templates) - { - var tId = 0; - if (int.TryParse(str, out tId)) - { - try - { - var t = new Template(tId); - var li = new ListItem(t.Text, t.Id.ToString()); - li.Selected = true; - templates.Items.Add(li); - } - catch - { - tempList.Add(str); - } - } - } - //removing failing template items from the uninstall manifest - SyncLists(_pack.Data.Templates, tempList); - - foreach (string str in _pack.Data.Stylesheets) - { - int tId = 0; - if (int.TryParse(str, out tId)) - { - try - { - var s = new StyleSheet(tId); - ListItem li = new ListItem(s.Text, s.Id.ToString()); - li.Selected = true; - stylesheets.Items.Add(li); - } - catch - { - tempList.Add(str); - } - } - } - //removing failing stylesheet items from the uninstall manifest - SyncLists(_pack.Data.Stylesheets, tempList); - - foreach (var str in _pack.Data.Macros) - { - var tId = 0; - if (int.TryParse(str, out tId)) - { - try - { - var m = new Macro(tId); - if (!string.IsNullOrEmpty(m.Name)) - { - //Macros need an extra check to see if they actually exists. For some reason the macro does not return null, if the id is not found... - var li = new ListItem(m.Name, m.Id.ToString()); - li.Selected = true; - macros.Items.Add(li); - } - else - { - tempList.Add(str); - } - } - catch - { - tempList.Add(str); - } - } - } - //removing failing macros items from the uninstall manifest - SyncLists(_pack.Data.Macros, tempList); - - foreach (var str in _pack.Data.Files) - { - try - { - if (!string.IsNullOrEmpty(str) && System.IO.File.Exists(IOHelper.MapPath(str) )) - { - var li = new ListItem(str, str); - li.Selected = true; - files.Items.Add(li); - } - else - { - tempList.Add(str); - } - - } - catch - { - tempList.Add(str); - } - } - - //removing failing files from the uninstall manifest - SyncLists(_pack.Data.Files, tempList); - - foreach (string str in _pack.Data.DictionaryItems) - { - var tId = 0; - - if (int.TryParse(str, out tId)) - { - try - { - var di = Services.LocalizationService.GetDictionaryItemById(tId); - if (di == null) continue; - - var li = new ListItem(di.ItemKey, di.Id.ToString()); - li.Selected = true; - - dictionaryItems.Items.Add(li); - } - catch - { - tempList.Add(str); - } - } - } - - //removing failing files from the uninstall manifest - SyncLists(_pack.Data.DictionaryItems, tempList); - - //TODO: Fix this with the new services and apis! and then remove since this should all be in angular - //foreach (var str in _pack.Data.DataTypes) - //{ - // var tId = 0; - - // if (int.TryParse(str, out tId)) - // { - // try - // { - // var dtd = new cms.businesslogic.datatype.DataTypeDefinition(tId); - - // if (dtd != null) - // { - // var li = new ListItem(dtd.Text, dtd.Id.ToString()); - // li.Selected = true; - - // dataTypes.Items.Add(li); - // } - // else - // { - // tempList.Add(str); - // } - // } - // catch - // { - // tempList.Add(str); - // } - // } - //} - - //removing failing files from the uninstall manifest - SyncLists(_pack.Data.DataTypes, tempList); - - //save the install manifest, so even tho the user doesn't uninstall, it stays uptodate. - _pack.Save(); - - - //Look for updates on packages. - if (!string.IsNullOrEmpty(_pack.Data.RepositoryGuid) && !string.IsNullOrEmpty(_pack.Data.PackageGuid)) - { - try - { - - _repo = cms.businesslogic.packager.repositories.Repository.getByGuid(_pack.Data.RepositoryGuid); - - if (_repo != null) - { - hl_packageRepo.Text = _repo.Name; - hl_packageRepo.NavigateUrl = "BrowseRepository.aspx?repoGuid=" + _repo.Guid; - pp_repository.Visible = true; - } - - var repoPackage = _repo.Webservice.PackageByGuid(_pack.Data.PackageGuid); - - if (repoPackage != null) - { - if (repoPackage.HasUpgrade && repoPackage.UpgradeVersion != _pack.Data.Version) - { - pane_upgrade.Visible = true; - lt_upgradeReadme.Text = repoPackage.UpgradeReadMe; - bt_gotoUpgrade.OnClientClick = "window.location.href = 'browseRepository.aspx?url=" + repoPackage.Url + "'; return true;"; - } - - if (!string.IsNullOrEmpty(repoPackage.Demo)) - { - lb_demoLink.OnClientClick = "openDemo(this, '" + _pack.Data.PackageGuid + "'); return false;"; - pp_documentation.Visible = true; - } - - if (!string.IsNullOrEmpty(repoPackage.Documentation)) - { - hl_docLink.NavigateUrl = repoPackage.Documentation; - hl_docLink.Target = "_blank"; - pp_documentation.Visible = true; - } - } - } - catch - { - pane_upgrade.Visible = false; - } - } - - - var deletePackage = true; - //sync the UI to match what is in the package - if (macros.Items.Count == 0) - pp_macros.Visible = false; - else - deletePackage = false; - - if (documentTypes.Items.Count == 0) - pp_docTypes.Visible = false; - else - deletePackage = false; - - if (files.Items.Count == 0) - pp_files.Visible = false; - else - deletePackage = false; - - if (templates.Items.Count == 0) - pp_templates.Visible = false; - else - deletePackage = false; - - if (stylesheets.Items.Count == 0) - pp_css.Visible = false; - else - deletePackage = false; - - if (dictionaryItems.Items.Count == 0) - pp_di.Visible = false; - else - deletePackage = false; - - if (dataTypes.Items.Count == 0) - pp_dt.Visible = false; - else - deletePackage = false; - - - if (deletePackage) - { - pane_noItems.Visible = true; - pane_uninstall.Visible = false; - } - - // List the package version history [LK 2013-067-10] - Version v; - var packageVersionHistory = cms.businesslogic.packager.InstalledPackage.GetAllInstalledPackages() - .Where(x => x.Data.Id != _pack.Data.Id && string.Equals(x.Data.Name, _pack.Data.Name, StringComparison.OrdinalIgnoreCase)) - .OrderBy(x => Version.TryParse(x.Data.Version, out v) ? v : new Version()); - - if (packageVersionHistory != null && packageVersionHistory.Any()) - { - rptr_versions.DataSource = packageVersionHistory; - rptr_versions.DataBind(); - - pane_versions.Visible = true; - } - } - } - } - - private static void SyncLists(List list, List removed) - { - foreach (var str in removed) - { - list.Remove(str); - } - - for (var i = 0; i < list.Count; i++) - { - if (String.IsNullOrEmpty(list[i].Trim())) - list.RemoveAt(i); - } - - removed.Clear(); - } - - protected void delPack(object sender, EventArgs e) - { - _pack.Delete(Security.CurrentUser.Id); - pane_uninstalled.Visible = true; - pane_uninstall.Visible = false; - } - - - protected void confirmUnInstall(object sender, EventArgs e) - { - var refreshCache = false; - - //Uninstall Stylesheets - foreach (ListItem li in stylesheets.Items) - { - if (li.Selected) - { - int nId; - - if (int.TryParse(li.Value, out nId)) - { - var s = new StyleSheet(nId); - s.delete(); - _pack.Data.Stylesheets.Remove(nId.ToString()); - } - } - } - - //Uninstall templates - foreach (ListItem li in templates.Items) - { - if (li.Selected) - { - int nId; - - if (int.TryParse(li.Value, out nId)) - { - var found = Services.FileService.GetTemplate(nId); - if (found != null) - { - Services.FileService.DeleteTemplate(found.Alias, Security.CurrentUser.Id); - } - _pack.Data.Templates.Remove(nId.ToString()); - } - } - } - - //Uninstall macros - foreach (ListItem li in macros.Items) - { - if (li.Selected) - { - int nId; - - if (int.TryParse(li.Value, out nId)) - { - var s = new Macro(nId); - if (!string.IsNullOrEmpty(s.Name)) - { - s.Delete(); - } - - _pack.Data.Macros.Remove(nId.ToString()); - } - } - } - - //Remove Document Types - var contentTypes = new List(); - var contentTypeService = Current.Services.ContentTypeService; - foreach (ListItem li in documentTypes.Items) - { - if (li.Selected) - { - int nId; - - if (int.TryParse(li.Value, out nId)) - { - var contentType = contentTypeService.Get(nId); - if (contentType != null) - { - contentTypes.Add(contentType); - _pack.Data.Documenttypes.Remove(nId.ToString(CultureInfo.InvariantCulture)); - // refresh content cache when document types are removed - refreshCache = true; - } - } - } - } - //Order the DocumentTypes before removing them - if (contentTypes.Any()) - { - //TODO: I don't think this ordering is necessary - var orderedTypes = (from contentType in contentTypes - orderby contentType.ParentId descending, contentType.Id descending - select contentType); - contentTypeService.Delete(orderedTypes); - } - - //Remove Dictionary items - foreach (ListItem li in dictionaryItems.Items) - { - if (li.Selected) - { - int nId; - - if (int.TryParse(li.Value, out nId)) - { - var di = Services.LocalizationService.GetDictionaryItemById(nId); - if (di != null) - { - Services.LocalizationService.Delete(di); - } - _pack.Data.DictionaryItems.Remove(nId.ToString()); - } - } - } - - //TODO: Fix this with the new services and apis! and then remove since this should all be in angular - - ////Remove Data types - //foreach (ListItem li in dataTypes.Items) - //{ - // if (li.Selected) - // { - // int nId; - - // if (int.TryParse(li.Value, out nId)) - // { - // var dtd = new cms.businesslogic.datatype.DataTypeDefinition(nId); - // dtd.delete(); - // _pack.Data.DataTypes.Remove(nId.ToString()); - // } - // } - //} - - _pack.Save(); - - if (!IsManifestEmpty()) - { - Response.Redirect(Request.RawUrl); - } - else - { - - // uninstall actions - try - { - var actionsXml = new XmlDocument(); - actionsXml.LoadXml("" + _pack.Data.Actions + ""); - - Current.Logger.Debug("executing undo actions: {0}", () => actionsXml.OuterXml); - - foreach (XmlNode n in actionsXml.DocumentElement.SelectNodes("//Action")) - { - try - { - cms.businesslogic.packager.PackageAction.UndoPackageAction(_pack.Data.Name, n.Attributes["alias"].Value, n); - } - catch (Exception ex) - { - Current.Logger.Error("An error occurred running undo actions", ex); - } - } - } - catch (Exception ex) - { - Current.Logger.Error("An error occurred running undo actions", ex); - } - - //moved remove of files here so custom package actions can still undo - //Remove files - foreach (ListItem li in files.Items) - { - if (li.Selected) - { - //here we need to try to find the file in question as most packages does not support the tilde char - - var file = IOHelper.FindFile(li.Value); - - var filePath = IOHelper.MapPath(file); - if (System.IO.File.Exists(filePath)) - { - System.IO.File.Delete(filePath); - _pack.Data.Files.Remove(li.Value); - } - } - } - _pack.Save(); - _pack.Delete(Security.CurrentUser.Id); - - pane_uninstalled.Visible = true; - pane_uninstall.Visible = false; - - } - - // refresh cache - if (refreshCache) - { - // library.RefreshContent is obsolete, would need to RefreshAllFacade, - // but it should be managed automatically by services and caches! - //DistributedCache.Instance.RefreshAllFacade(); - } - - //ensure that all tree's are refreshed after uninstall - ClientTools.ClearClientTreeCache() - .RefreshTree(); - - TreeDefinitionCollection.Instance.ReRegisterTrees(); - } - - private bool IsManifestEmpty() - { - - _pack.Data.Documenttypes.TrimExcess(); - _pack.Data.Files.TrimExcess(); - _pack.Data.Macros.TrimExcess(); - _pack.Data.Stylesheets.TrimExcess(); - _pack.Data.Templates.TrimExcess(); - _pack.Data.DataTypes.TrimExcess(); - _pack.Data.DictionaryItems.TrimExcess(); - - var lists = new List> - { - _pack.Data.Documenttypes, - _pack.Data.Macros, - _pack.Data.Stylesheets, - _pack.Data.Templates, - _pack.Data.DictionaryItems, - _pack.Data.DataTypes - }; - - //Not including files, since there might be assemblies that contain package actions - //lists.Add(pack.Data.Files); - - return lists.SelectMany(list => list).All(str => string.IsNullOrEmpty(str.Trim())); - } - - protected override void OnInit(EventArgs e) - { - base.OnInit(e); - - Panel1.Text = Services.TextService.Localize("treeHeaders/installedPackages"); - pane_meta.Text = Services.TextService.Localize("packager/packageMetaData"); - pp_name.Text = Services.TextService.Localize("packager/packageName"); - pp_version.Text = Services.TextService.Localize("packager/packageVersion"); - pp_author.Text = Services.TextService.Localize("packager/packageAuthor"); - pp_repository.Text = Services.TextService.Localize("packager/packageRepository"); - pp_documentation.Text = Services.TextService.Localize("packager/packageDocumentation"); - pp_readme.Text = Services.TextService.Localize("packager/packageReadme"); - hl_docLink.Text = Services.TextService.Localize("packager/packageDocumentation"); - lb_demoLink.Text = Services.TextService.Localize("packager/packageDemonstration"); - - pane_versions.Text = Services.TextService.Localize("packager/packageVersionHistory"); - pane_noItems.Text = Services.TextService.Localize("packager/packageNoItemsHeader"); - - pane_uninstall.Text = Services.TextService.Localize("packager/packageUninstallHeader"); - bt_deletePackage.Text = Services.TextService.Localize("packager/packageUninstallHeader"); - bt_confirmUninstall.Text = Services.TextService.Localize("packager/packageUninstallConfirm"); - - pane_uninstalled.Text = Services.TextService.Localize("packager/packageUninstalledHeader"); - - var general = Panel1.NewTabPage(Services.TextService.Localize("packager/packageName")); - general.Controls.Add(pane_meta); - general.Controls.Add(pane_versions); - - - var uninstall = Panel1.NewTabPage(Services.TextService.Localize("packager/packageUninstallHeader")); - uninstall.Controls.Add(pane_noItems); - uninstall.Controls.Add(pane_uninstall); - uninstall.Controls.Add(pane_uninstalled); - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.designer.cs deleted file mode 100644 index 10c933e861..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Packages/installedPackage.aspx.designer.cs +++ /dev/null @@ -1,402 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.presentation.developer.packages { - - - public partial class installedPackage { - - /// - /// Panel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.TabView Panel1; - - /// - /// pane_meta control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_meta; - - /// - /// pp_name control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_name; - - /// - /// lt_packagename control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal lt_packagename; - - /// - /// pp_version control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_version; - - /// - /// lt_packageVersion control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal lt_packageVersion; - - /// - /// pp_author control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_author; - - /// - /// lt_packageAuthor control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal lt_packageAuthor; - - /// - /// pp_documentation control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_documentation; - - /// - /// hl_docLink control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink hl_docLink; - - /// - /// lb_demoLink control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton lb_demoLink; - - /// - /// pp_repository control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_repository; - - /// - /// hl_packageRepo control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink hl_packageRepo; - - /// - /// pp_readme control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_readme; - - /// - /// lt_readme control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal lt_readme; - - /// - /// pane_versions control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_versions; - - /// - /// pp_versions control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_versions; - - /// - /// rptr_versions control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Repeater rptr_versions; - - /// - /// pane_upgrade control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_upgrade; - - /// - /// pp_upgradeInstruction control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_upgradeInstruction; - - /// - /// lt_upgradeReadme control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal lt_upgradeReadme; - - /// - /// bt_gotoUpgrade control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_gotoUpgrade; - - /// - /// pane_noItems control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_noItems; - - /// - /// bt_deletePackage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_deletePackage; - - /// - /// pane_uninstall control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_uninstall; - - /// - /// pp_docTypes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_docTypes; - - /// - /// documentTypes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList documentTypes; - - /// - /// pp_templates control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_templates; - - /// - /// templates control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList templates; - - /// - /// pp_css control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_css; - - /// - /// stylesheets control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList stylesheets; - - /// - /// pp_macros control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_macros; - - /// - /// macros control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList macros; - - /// - /// pp_files control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_files; - - /// - /// files control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList files; - - /// - /// pp_di control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_di; - - /// - /// dictionaryItems control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList dictionaryItems; - - /// - /// pp_dt control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_dt; - - /// - /// dataTypes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBoxList dataTypes; - - /// - /// pp_confirm control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_confirm; - - /// - /// bt_confirmUninstall control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button bt_confirmUninstall; - - /// - /// progbar control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.ProgressBar progbar; - - /// - /// pane_uninstalled control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_uninstalled; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/users/PermissionEditor.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/users/PermissionEditor.aspx index 815a420f88..75b5d6e66a 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/users/PermissionEditor.aspx +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/users/PermissionEditor.aspx @@ -1,5 +1,5 @@ <%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../masterpages/umbracoPage.Master" CodeBehind="PermissionEditor.aspx.cs" Inherits="umbraco.cms.presentation.user.PermissionEditor" %> - +<%@ Import Namespace="Umbraco.Web" %> <%@ Register Src="../controls/Tree/TreeControl.ascx" TagName="TreeControl" TagPrefix="umbraco" %> <%@ Register Src="NodePermissions.ascx" TagName="NodePermissions" TagPrefix="user" %> <%@ Register TagPrefix="ui" Namespace="umbraco.uicontrols" Assembly="controls" %> @@ -27,7 +27,7 @@