Compare commits
161 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf86409e3f | |||
| 134f5e2601 | |||
| 37ac524e8e | |||
| 43af2f8e55 | |||
| a20584e3de | |||
| 19ec26fef9 | |||
| 527f98189a | |||
| 78c289a559 | |||
| 646abb3aea | |||
| 2af59471a2 | |||
| b76b09026b | |||
| 090f89e5b6 | |||
| 4870afd2d3 | |||
| 80257b6684 | |||
| 8f3a0b6919 | |||
| 9fd2f34343 | |||
| e774717346 | |||
| 5f5759c8a3 | |||
| 0b90097aad | |||
| 7cd540c37e | |||
| 83595ecaf5 | |||
| e07c5e6ff8 | |||
| 67ff827d67 | |||
| 3f7159797f | |||
| 6f81b7fe24 | |||
| f2819f61e5 | |||
| 2107e9d9e3 | |||
| c623b448ba | |||
| 8bb49f57e8 | |||
| da0b1c2f23 | |||
| a288fc62eb | |||
| 82e50ccd3a | |||
| 15b0dc9f29 | |||
| 8057d09fc2 | |||
| 8877100bf0 | |||
| 41c96e6e26 | |||
| abdd117264 | |||
| 6272dac698 | |||
| 7a4b5fa796 | |||
| c962132ee0 | |||
| 0780979469 | |||
| a42e568fdf | |||
| e62661cc6a | |||
| 6841b2ac61 | |||
| f7f4276485 | |||
| bb9e23ca3e | |||
| 10db9363f4 | |||
| 7d5d69e2e3 | |||
| 06897aa8c6 | |||
| ee75158dd0 | |||
| c022397d86 | |||
| e25f6e82ed | |||
| d104525a50 | |||
| b0a64aa4b5 | |||
| ca86385269 | |||
| fb8368267e | |||
| ef4322a9b3 | |||
| 7032e137b8 | |||
| e99643ecfd | |||
| a325529eb8 | |||
| c68f832be6 | |||
| 4ab1c51327 | |||
| 6f39bac32a | |||
| e007a37c36 | |||
| ab9e029525 | |||
| d298388a7b | |||
| 4463abe9bb | |||
| d1db38182f | |||
| e808360653 | |||
| c5df712471 | |||
| 2f67008987 | |||
| 1672e284c5 | |||
| 60ce36a7f2 | |||
| 05c12d1f27 | |||
| 72e2cacc87 | |||
| 4285102422 | |||
| 5ffdf4dd60 | |||
| abbcf0e26b | |||
| 347b25472f | |||
| b745948dc6 | |||
| 8007c8869f | |||
| b51a328ead | |||
| f61437cc7c | |||
| f3b8f2eb5f | |||
| de4628f450 | |||
| b0a64655b4 | |||
| 48d88ec8fa | |||
| 7ca151a3fa | |||
| 363c8fab2c | |||
| 8d4fd9d1cf | |||
| 24071eb3b1 | |||
| 62ffbe7cf0 | |||
| f2d6b47e47 | |||
| f3541908c7 | |||
| 4e57e1cc18 | |||
| 410afffaa9 | |||
| 936e94789d | |||
| 468a56e5de | |||
| 468ec8824a | |||
| cad913b7a1 | |||
| 382103d99d | |||
| cbb6b9bca0 | |||
| a1b90a50cd | |||
| 9ea5855073 | |||
| 4a37433042 | |||
| 91469812d3 | |||
| 68a8eb7f3f | |||
| 2e7baabb94 | |||
| 57745fe71d | |||
| de6f9236e7 | |||
| a00c59e8b5 | |||
| 05c2da807f | |||
| 0fd8ca43d6 | |||
| 87f09b2ee6 | |||
| e466878925 | |||
| 7adf917570 | |||
| 7c41db4bcc | |||
| 5caaef7795 | |||
| 3b72945b1f | |||
| 71eb22d0e8 | |||
| 9d780a2e8f | |||
| 55b00069cb | |||
| b304728f4e | |||
| 319acc199e | |||
| 2a982f21a7 | |||
| 3ff455f11d | |||
| 41ad1bf27b | |||
| f49d939a2d | |||
| c7e80fc532 | |||
| b47d691841 | |||
| 7e1e83b493 | |||
| f6971185f8 | |||
| 244429b972 | |||
| 80ceba36dc | |||
| 2b5f370c92 | |||
| 3d90c2b83f | |||
| 3b8b5b6dfa | |||
| 42959a1db5 | |||
| a1cd22208b | |||
| 0bc4c7e2aa | |||
| 9f6e6e4701 | |||
| 34ba3f3351 | |||
| dcfb8b94d8 | |||
| f5f3676a56 | |||
| dc7b83ca6c | |||
| fcf9dcd803 | |||
| 3556043b55 | |||
| fef9e3fde0 | |||
| e849d2d0d0 | |||
| 9a6123579f | |||
| 591a881283 | |||
| 1554d52ea9 | |||
| 60924d93fb | |||
| 50335723b0 | |||
| 58697eaa04 | |||
| ce58ad91b5 | |||
| 77162e4b51 | |||
| 6c172702be | |||
| 7c72e70967 | |||
| 75b74a6687 | |||
| 7dcb4435d8 |
+11
-5
@@ -1,10 +1,16 @@
|
||||
root=true
|
||||
# editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Default settings:
|
||||
# A newline ending every file
|
||||
# Use 4 spaces as indentation
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
|
||||
indent_size = 4
|
||||
# Trim trailing whitespace, limited support.
|
||||
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
|
||||
trim_trailing_whitespace = true
|
||||
@@ -0,0 +1,49 @@
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
|
||||
*.cs text=auto diff=csharp
|
||||
*.vb text=auto
|
||||
*.c text=auto
|
||||
*.cpp text=auto
|
||||
*.cxx text=auto
|
||||
*.h text=auto
|
||||
*.hxx text=auto
|
||||
*.py text=auto
|
||||
*.rb text=auto
|
||||
*.java text=auto
|
||||
*.html text=auto
|
||||
*.htm text=auto
|
||||
*.css text=auto
|
||||
*.scss text=auto
|
||||
*.sass text=auto
|
||||
*.less text=auto
|
||||
*.js text=auto
|
||||
*.lisp text=auto
|
||||
*.clj text=auto
|
||||
*.sql text=auto
|
||||
*.php text=auto
|
||||
*.lua text=auto
|
||||
*.m text=auto
|
||||
*.asm text=auto
|
||||
*.erl text=auto
|
||||
*.fs text=auto
|
||||
*.fsx text=auto
|
||||
*.hs text=auto
|
||||
|
||||
*.csproj text=auto merge=union
|
||||
*.vbproj text=auto merge=union
|
||||
*.fsproj text=auto merge=union
|
||||
*.dbproj text=auto merge=union
|
||||
*.sln text=auto eol=crlf merge=union
|
||||
@@ -44,7 +44,7 @@ function Build-UmbracoDocs
|
||||
# change baseUrl
|
||||
$baseUrl = "https://our.umbraco.org/apidocs/ui/"
|
||||
$indexPath = "$src/Umbraco.Web.UI.Client/docs/api/index.html"
|
||||
(Get-Content $indexPath).Replace("location.href.replace(rUrl, indexFile)", "'$baseUrl'") `
|
||||
(Get-Content $indexPath).Replace("origin + location.href.substr(origin.length).replace(rUrl, indexFile)", "'$baseUrl'") `
|
||||
| Set-Content $indexPath
|
||||
|
||||
# restore
|
||||
@@ -100,8 +100,9 @@ function Get-DocFx($uenv, $buildTemp)
|
||||
$docFx = "$buildTemp\docfx"
|
||||
if (-not (test-path $docFx))
|
||||
{
|
||||
Write-Host "Download DocFx..."
|
||||
$source = "https://github.com/dotnet/docfx/releases/download/v2.19.2/docfx.zip"
|
||||
Write-Host "Download DocFx from $source"
|
||||
|
||||
Invoke-WebRequest $source -OutFile "$buildTemp\docfx.zip"
|
||||
|
||||
&$uenv.Zip x "$buildTemp\docfx.zip" -o"$buildTemp\docfx" -aos > $nul
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.4, 2.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.8, 4.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.10, 4.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
|
||||
</dependencies>
|
||||
|
||||
@@ -98,10 +98,26 @@ if ($project) {
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
} else {
|
||||
# This part only runs for upgrades
|
||||
|
||||
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
|
||||
$upgradeView = Join-Path $umbracoFolder "Views\install\"
|
||||
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
|
||||
Copy-Item $upgradeViewSource $upgradeView -Force
|
||||
|
||||
Try
|
||||
{
|
||||
# Disable tours for upgrades, presumably Umbraco experience is already available
|
||||
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
|
||||
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
|
||||
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
|
||||
# Reference: https://stackoverflow.com/a/32951824/5018
|
||||
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
# Not a big problem if this fails, let it go
|
||||
}
|
||||
}
|
||||
|
||||
$installFolder = Join-Path $projectPath "Install"
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.8.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.8.0-beta007")]
|
||||
[assembly: AssemblyInformationalVersion("7.8.0")]
|
||||
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a composite key of (Type, Type) for fast dictionaries.
|
||||
/// </summary>
|
||||
internal struct CompositeTypeTypeKey : IEquatable<CompositeTypeTypeKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeTypeTypeKey"/> struct.
|
||||
/// </summary>
|
||||
public CompositeTypeTypeKey(Type type1, Type type2) : this()
|
||||
{
|
||||
Type1 = type1;
|
||||
Type2 = type2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first type.
|
||||
/// </summary>
|
||||
public Type Type1 { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the second type.
|
||||
/// </summary>
|
||||
public Type Type2 { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(CompositeTypeTypeKey other)
|
||||
{
|
||||
return Type1 == other.Type1 && Type2 == other.Type2;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj is CompositeTypeTypeKey ? (CompositeTypeTypeKey)obj : default(CompositeTypeTypeKey);
|
||||
return Type1 == other.Type1 && Type2 == other.Type2;
|
||||
}
|
||||
|
||||
public static bool operator ==(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
|
||||
{
|
||||
return key1.Type1 == key2.Type1 && key1.Type2 == key2.Type2;
|
||||
}
|
||||
|
||||
public static bool operator !=(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
|
||||
{
|
||||
return key1.Type1 != key2.Type1 || key1.Type2 != key2.Type2;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (Type1.GetHashCode() * 397) ^ Type2.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,17 +11,53 @@
|
||||
/// The integer identifier for global system root node.
|
||||
/// </summary>
|
||||
public const int Root = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifier for global system root node.
|
||||
/// </summary>
|
||||
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
|
||||
public const string RootString = "-1";
|
||||
|
||||
/// <summary>
|
||||
/// The integer identifier for content's recycle bin.
|
||||
/// </summary>
|
||||
public const int RecycleBinContent = -20;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifier for content's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
|
||||
public const string RecycleBinContentString = "-20";
|
||||
|
||||
/// <summary>
|
||||
/// The string path prefix of the content's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Everything that is in the content recycle bin, has a path that starts with the prefix.</para>
|
||||
/// <para>Use this instead of re-creating the string everywhere.</para>
|
||||
/// </remarks>
|
||||
public const string RecycleBinContentPathPrefix = "-1,-20,";
|
||||
|
||||
/// <summary>
|
||||
/// The integer identifier for media's recycle bin.
|
||||
/// </summary>
|
||||
public const int RecycleBinMedia = -21;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifier for media's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
|
||||
public const string RecycleBinMediaString = "-21";
|
||||
|
||||
/// <summary>
|
||||
/// The string path prefix of the media's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Everything that is in the media recycle bin, has a path that starts with the prefix.</para>
|
||||
/// <para>Use this instead of re-creating the string everywhere.</para>
|
||||
/// </remarks>
|
||||
public const string RecycleBinMediaPathPrefix = "-1,-21,";
|
||||
|
||||
public const int DefaultContentListViewDataTypeId = -95;
|
||||
public const int DefaultMediaListViewDataTypeId = -96;
|
||||
public const int DefaultMembersListViewDataTypeId = -97;
|
||||
@@ -29,6 +65,6 @@
|
||||
public const string UmbracoConnectionName = "umbracoDbDSN";
|
||||
public const string UmbracoMigrationName = "Umbraco";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ namespace Umbraco.Core
|
||||
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
|
||||
{
|
||||
if (truncateTo == DateTruncate.Year)
|
||||
return new DateTime(dt.Year, 0, 0);
|
||||
return new DateTime(dt.Year, 1, 1);
|
||||
if (truncateTo == DateTruncate.Month)
|
||||
return new DateTime(dt.Year, dt.Month, 0);
|
||||
return new DateTime(dt.Year, dt.Month, 1);
|
||||
if (truncateTo == DateTruncate.Day)
|
||||
return new DateTime(dt.Year, dt.Month, dt.Day);
|
||||
if (truncateTo == DateTruncate.Hour)
|
||||
@@ -41,43 +41,43 @@ namespace Umbraco.Core
|
||||
Hour,
|
||||
Minute,
|
||||
Second
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
|
||||
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
|
||||
/// date time is before the time, calculate onto next day)
|
||||
/// </summary>
|
||||
/// <param name="fromDateTime">Date to start from</param>
|
||||
/// <param name="scheduledTime">Time to compare against (in Hmm form, e.g. 330, 2200)</param>
|
||||
/// <returns></returns>
|
||||
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
|
||||
{
|
||||
// Ensure time provided is 4 digits long
|
||||
if (scheduledTime.Length == 3)
|
||||
{
|
||||
scheduledTime = "0" + scheduledTime;
|
||||
}
|
||||
|
||||
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
|
||||
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
|
||||
|
||||
DateTime scheduledDateTime;
|
||||
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
|
||||
{
|
||||
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var nextDay = fromDateTime.AddDays(1);
|
||||
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
|
||||
}
|
||||
|
||||
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
|
||||
}
|
||||
|
||||
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
|
||||
{
|
||||
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
|
||||
/// <returns></returns>
|
||||
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
|
||||
{
|
||||
// Ensure time provided is 4 digits long
|
||||
if (scheduledTime.Length == 3)
|
||||
{
|
||||
scheduledTime = "0" + scheduledTime;
|
||||
}
|
||||
|
||||
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
|
||||
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
|
||||
|
||||
DateTime scheduledDateTime;
|
||||
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
|
||||
{
|
||||
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var nextDay = fromDateTime.AddDays(1);
|
||||
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
|
||||
}
|
||||
|
||||
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
|
||||
}
|
||||
|
||||
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
|
||||
{
|
||||
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Packaging.Models;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
@@ -7,18 +8,27 @@ namespace Umbraco.Core.Events
|
||||
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
{
|
||||
private readonly MetaData _packageMetaData;
|
||||
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the overload specifying packageMetaData instead")]
|
||||
public ImportPackageEventArgs(TEntity eventObject, bool canCancel)
|
||||
: base(new[] { eventObject }, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
|
||||
: base(new[] { eventObject })
|
||||
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData, bool canCancel)
|
||||
: base(new[] { eventObject }, canCancel)
|
||||
{
|
||||
if (packageMetaData == null) throw new ArgumentNullException("packageMetaData");
|
||||
_packageMetaData = packageMetaData;
|
||||
}
|
||||
|
||||
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
|
||||
: this(eventObject, packageMetaData, true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MetaData PackageMetaData
|
||||
{
|
||||
get { return _packageMetaData; }
|
||||
|
||||
@@ -95,8 +95,10 @@ namespace Umbraco.Core.Models
|
||||
get { return _allowedTemplates; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector,
|
||||
Ps.Value.TemplateComparer);
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector, Ps.Value.TemplateComparer);
|
||||
|
||||
if (_allowedTemplates.Any(x => x.Id == _defaultTemplate) == false)
|
||||
DefaultTemplateId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
var name = Name;
|
||||
|
||||
// cater for instances where node has no name.
|
||||
if(string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return _numPos;
|
||||
}
|
||||
|
||||
if (name[name.Length - 1] != ')')
|
||||
return _numPos = -1;
|
||||
|
||||
@@ -106,7 +112,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
return uniqueing ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
|
||||
return uniqueing || string.IsNullOrWhiteSpace(nodeName) ? string.Concat(nodeName, " (", uniqueNumber.ToString(), ")") : nodeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -18,6 +18,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
return Constants.PropertyEditors.MultipleTextstringAlias.Equals(propertyType.PropertyEditorAlias);
|
||||
}
|
||||
|
||||
private static readonly string[] NewLineDelimiters = { "\r\n", "\r", "\n" };
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
// data is (both in database and xml):
|
||||
@@ -53,7 +55,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
// Fall back on normal behaviour
|
||||
if (values.Any() == false)
|
||||
{
|
||||
return sourceString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
return sourceString.Split(NewLineDelimiters, StringSplitOptions.None);
|
||||
}
|
||||
|
||||
return values.ToArray();
|
||||
|
||||
@@ -401,9 +401,10 @@ namespace Umbraco.Core.Publishing
|
||||
content.Name, content.Id));
|
||||
}
|
||||
|
||||
// if newest is published, unpublish
|
||||
if (content.Published)
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
// make sure we dirty .Published and always unpublish
|
||||
// the version we have here could be the newest, !Published
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
|
||||
_logger.Info<PublishingStrategy>(
|
||||
string.Format("Content '{0}' with Id '{1}' has been unpublished.",
|
||||
|
||||
@@ -116,5 +116,19 @@ namespace Umbraco.Core.Scoping
|
||||
Enlisted[key] = enlistedOfT;
|
||||
return enlistedOfT.Item;
|
||||
}
|
||||
|
||||
public T GetEnlisted<T>(string key)
|
||||
{
|
||||
var enlistedObjects = _enlisted;
|
||||
if (enlistedObjects == null) return default (T);
|
||||
|
||||
IEnlistedObject enlisted;
|
||||
if (enlistedObjects.TryGetValue(key, out enlisted) == false)
|
||||
return default (T);
|
||||
|
||||
var enlistedAs = enlisted as EnlistedObject<T>;
|
||||
if (enlistedAs == null) throw new InvalidOperationException("An item with the key exists, but with a different type.");
|
||||
return enlistedAs.Item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -692,7 +692,7 @@ namespace Umbraco.Core.Services
|
||||
totalChildren = 0;
|
||||
return Enumerable.Empty<IContent>();
|
||||
}
|
||||
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0]), TextColumnType.NVarchar));
|
||||
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0].Path), TextColumnType.NVarchar));
|
||||
}
|
||||
|
||||
|
||||
@@ -737,7 +737,7 @@ namespace Umbraco.Core.Services
|
||||
totalChildren = 0;
|
||||
return Enumerable.Empty<IContent>();
|
||||
}
|
||||
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0]), TextColumnType.NVarchar));
|
||||
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", contentPath[0].Path), TextColumnType.NVarchar));
|
||||
}
|
||||
|
||||
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
|
||||
@@ -884,8 +884,8 @@ namespace Umbraco.Core.Services
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateContentRepository(uow);
|
||||
var query = Query<IContent>.Builder.Where(x => x.Published && x.ExpireDate <= DateTime.Now);
|
||||
return repository.GetByQuery(query);
|
||||
var query = Query<IContent>.Builder.Where(x => x.ExpireDate <= DateTime.Now);
|
||||
return repository.GetByQuery(query).Where(x => x.HasPublishedVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,13 +912,11 @@ namespace Umbraco.Core.Services
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateContentRepository(uow);
|
||||
var query = Query<IContent>.Builder.Where(x => x.Path.Contains(Constants.System.RecycleBinContent.ToInvariantString()));
|
||||
var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith(Constants.System.RecycleBinContentPathPrefix));
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether an <see cref="IContent"/> item has any children
|
||||
/// </summary>
|
||||
@@ -1344,6 +1342,40 @@ namespace Umbraco.Core.Services
|
||||
return content;
|
||||
}
|
||||
|
||||
public void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0)
|
||||
{
|
||||
using (new WriteLock(Locker))
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
var repository = RepositoryFactory.CreateContentBlueprintRepository(uow);
|
||||
|
||||
var contentTypeIdsA = contentTypeIds.ToArray();
|
||||
var query = new Query<IContent>();
|
||||
if (contentTypeIdsA.Length > 0)
|
||||
{
|
||||
query.Where(x => contentTypeIdsA.Contains(x.ContentTypeId));
|
||||
}
|
||||
var blueprints = repository.GetByQuery(query).Select(x =>
|
||||
{
|
||||
((Content) x).IsBlueprint = true;
|
||||
return x;
|
||||
}).ToArray();
|
||||
|
||||
foreach (var blueprint in blueprints)
|
||||
{
|
||||
repository.Delete(blueprint);
|
||||
}
|
||||
|
||||
uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs<IContent>(blueprints), "DeletedBlueprint");
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteBlueprintsOfType(int contentTypeId, int userId = 0)
|
||||
{
|
||||
DeleteBlueprintsOfTypes(new[] {contentTypeId}, userId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a single <see cref="IContent"/> object
|
||||
/// </summary>
|
||||
|
||||
@@ -920,7 +920,9 @@ namespace Umbraco.Core.Services
|
||||
var deletedContentTypes = new List<IContentType> { contentType };
|
||||
deletedContentTypes.AddRange(GetDescendants(contentType));
|
||||
|
||||
_contentService.DeleteContentOfTypes(deletedContentTypes.Select(x => x.Id), userId);
|
||||
var ids = deletedContentTypes.Select(x => x.Id).ToArray();
|
||||
_contentService.DeleteContentOfTypes(ids, userId);
|
||||
_contentService.DeleteBlueprintsOfTypes(ids);
|
||||
|
||||
repository.Delete(contentType);
|
||||
deleteEventArgs.DeletedEntities = deletedContentTypes.DistinctBy(x => x.Id);
|
||||
|
||||
@@ -101,7 +101,9 @@ namespace Umbraco.Core.Services
|
||||
IContent GetBlueprintById(Guid id);
|
||||
void SaveBlueprint(IContent content, int userId = 0);
|
||||
void DeleteBlueprint(IContent content, int userId = 0);
|
||||
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
|
||||
IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0);
|
||||
void DeleteBlueprintsOfType(int contentTypeId, int userId = 0);
|
||||
void DeleteBlueprintsOfTypes(IEnumerable<int> contentTypeIds, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all XML entries found in the cmsContentXml table based on the given path
|
||||
|
||||
@@ -389,7 +389,7 @@ namespace Umbraco.Core.Services
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateMediaRepository(uow);
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == level && x.Path.StartsWith("-21") == false);
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == level && x.Path.StartsWith(Constants.System.RecycleBinMediaPathPrefix) == false);
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
@@ -440,7 +440,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
|
||||
public IEnumerable<IMedia> GetAncestors(IMedia media)
|
||||
{
|
||||
var ids = media.Path.Split(',').Where(x => x != "-1" && x != media.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
|
||||
var ids = media.Path.Split(',').Where(x => x != Constants.System.RootString && x != media.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
|
||||
if (ids.Any() == false)
|
||||
return new List<IMedia>();
|
||||
|
||||
@@ -609,7 +609,7 @@ namespace Umbraco.Core.Services
|
||||
totalChildren = 0;
|
||||
return Enumerable.Empty<IMedia>();
|
||||
}
|
||||
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", mediaPath[0]), TextColumnType.NVarchar));
|
||||
query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", mediaPath[0].Path), TextColumnType.NVarchar));
|
||||
}
|
||||
IQuery<IMedia> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
@@ -673,7 +673,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>Parent <see cref="IMedia"/> object</returns>
|
||||
public IMedia GetParent(IMedia media)
|
||||
{
|
||||
if (media.ParentId == -1 || media.ParentId == -21)
|
||||
if (media.ParentId == Constants.System.Root || media.ParentId == Constants.System.RecycleBinMedia)
|
||||
return null;
|
||||
|
||||
return GetById(media.ParentId);
|
||||
@@ -703,7 +703,7 @@ namespace Umbraco.Core.Services
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateMediaRepository(uow);
|
||||
var query = Query<IMedia>.Builder.Where(x => x.ParentId == -1);
|
||||
var query = Query<IMedia>.Builder.Where(x => x.ParentId == Constants.System.Root);
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
@@ -717,7 +717,7 @@ namespace Umbraco.Core.Services
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateMediaRepository(uow);
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Path.Contains("-21"));
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Path.StartsWith(Constants.System.RecycleBinMediaPathPrefix));
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
@@ -767,7 +767,7 @@ namespace Umbraco.Core.Services
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
//This ensures that the correct method is called if this method is used to Move to recycle bin.
|
||||
if (parentId == -21)
|
||||
if (parentId == Constants.System.RecycleBinMedia)
|
||||
{
|
||||
MoveToRecycleBin(media, userId);
|
||||
return;
|
||||
@@ -868,7 +868,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var repository = RepositoryFactory.CreateMediaRepository(uow);
|
||||
repository.Delete(media);
|
||||
deleteEventArgs.CanCancel = false;
|
||||
deleteEventArgs.CanCancel = false;
|
||||
uow.Events.Dispatch(Deleted, this, deleteEventArgs);
|
||||
|
||||
Audit(uow, AuditType.Delete, "Delete Media performed by user", userId, media.Id);
|
||||
@@ -1003,7 +1003,7 @@ namespace Umbraco.Core.Services
|
||||
recycleBinEventArgs.RecycleBinEmptiedSuccessfully = success;
|
||||
uow.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs);
|
||||
|
||||
Audit(uow, AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
|
||||
Audit(uow, AuditType.Delete, "Empty Media Recycle Bin performed by user", 0, Constants.System.RecycleBinMedia);
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,7 +695,7 @@ namespace Umbraco.Core.Services
|
||||
IQuery<IMember> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
filterQuery = Query<IMember>.Builder.Where(x => x.Name.Contains(filter) || x.Username.Contains(filter));
|
||||
filterQuery = Query<IMember>.Builder.Where(x => x.Name.Contains(filter) || x.Username.Contains(filter) || x.Email.Contains(filter));
|
||||
}
|
||||
|
||||
var repository = RepositoryFactory.CreateMemberRepository(uow);
|
||||
|
||||
@@ -1748,9 +1748,10 @@ namespace Umbraco.Core.Services
|
||||
|
||||
internal InstallationSummary InstallPackage(string packageFilePath, int userId = 0, bool raiseEvents = false)
|
||||
{
|
||||
var metaData = GetPackageMetaData(packageFilePath);
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
var metaData = GetPackageMetaData(packageFilePath);
|
||||
{
|
||||
if (ImportingPackage.IsRaisedEventCancelled(new ImportPackageEventArgs<string>(packageFilePath, metaData), this))
|
||||
{
|
||||
var initEmpty = new InstallationSummary().InitEmpty();
|
||||
@@ -1762,7 +1763,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
if (raiseEvents)
|
||||
{
|
||||
ImportedPackage.RaiseEvent(new ImportPackageEventArgs<InstallationSummary>(installationSummary, false), this);
|
||||
ImportedPackage.RaiseEvent(new ImportPackageEventArgs<InstallationSummary>(installationSummary, metaData, false), this);
|
||||
}
|
||||
|
||||
return installationSummary;
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Umbraco.Core.Strings
|
||||
{
|
||||
foreach (var node in _umbracoSettings.RequestHandler.CharCollection)
|
||||
{
|
||||
if(string.IsNullOrEmpty(node.Char) == false)
|
||||
if (string.IsNullOrEmpty(node.Char) == false)
|
||||
_urlReplaceCharacters[node.Char] = node.Replacement;
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Strings
|
||||
private void EnsureNotFrozen()
|
||||
{
|
||||
if (_frozen)
|
||||
throw new InvalidOperationException("Cannot configure the helper once it is frozen.");
|
||||
throw new InvalidOperationException("Cannot configure the helper once it is frozen.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +176,7 @@ namespace Umbraco.Core.Strings
|
||||
}).WithConfig(CleanStringType.Alias, new Config
|
||||
{
|
||||
PreFilter = ApplyUrlReplaceCharacters,
|
||||
IsTerm = (c, leading) => leading
|
||||
IsTerm = (c, leading) => leading
|
||||
? char.IsLetter(c) // only letters
|
||||
: (char.IsLetterOrDigit(c) || c == '_'), // letter, digit or underscore
|
||||
StringType = CleanStringType.Ascii | CleanStringType.UmbracoCase,
|
||||
@@ -215,12 +215,12 @@ namespace Umbraco.Core.Strings
|
||||
return new Config
|
||||
{
|
||||
PreFilter = PreFilter,
|
||||
PostFilter = PostFilter,
|
||||
PostFilter = PostFilter,
|
||||
IsTerm = IsTerm,
|
||||
StringType = StringType,
|
||||
BreakTermsOnUpper = BreakTermsOnUpper,
|
||||
CutAcronymOnNonUpper = CutAcronymOnNonUpper,
|
||||
GreedyAcronyms = GreedyAcronyms,
|
||||
CutAcronymOnNonUpper = CutAcronymOnNonUpper,
|
||||
GreedyAcronyms = GreedyAcronyms,
|
||||
Separator = Separator
|
||||
};
|
||||
}
|
||||
@@ -338,9 +338,9 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// Gets the JavaScript code defining client-side short string services.
|
||||
/// </summary>
|
||||
public string GetShortStringServicesJavaScript(string controllerPath)
|
||||
{
|
||||
return string.Format(SssjsFormat,
|
||||
_umbracoSettings.Content.ForceSafeAliases ? "true" : "false", controllerPath);
|
||||
{
|
||||
return string.Format(SssjsFormat,
|
||||
_umbracoSettings.Content.ForceSafeAliases ? "true" : "false", controllerPath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -467,7 +467,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// Cleans a string.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to clean.</param>
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// strings are cleaned up to camelCase and Ascii.</param>
|
||||
/// <returns>The clean string.</returns>
|
||||
/// <remarks>The string is cleaned in the context of the default culture.</remarks>
|
||||
@@ -480,7 +480,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// Cleans a string, using a specified separator.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to clean.</param>
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// strings are cleaned up to camelCase and Ascii.</param>
|
||||
/// <param name="separator">The separator.</param>
|
||||
/// <returns>The clean string.</returns>
|
||||
@@ -494,7 +494,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// Cleans a string in the context of a specified culture.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to clean.</param>
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// strings are cleaned up to camelCase and Ascii.</param>
|
||||
/// <param name="culture">The culture.</param>
|
||||
/// <returns>The clean string.</returns>
|
||||
@@ -507,7 +507,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// Cleans a string in the context of a specified culture, using a specified separator.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to clean.</param>
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// <param name="stringType">A flag indicating the target casing and encoding of the string. By default,
|
||||
/// strings are cleaned up to camelCase and Ascii.</param>
|
||||
/// <param name="separator">The separator.</param>
|
||||
/// <param name="culture">The culture.</param>
|
||||
@@ -554,7 +554,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
text = Utf8ToAsciiConverter.ToAsciiString(text);
|
||||
break;
|
||||
case CleanStringType.TryAscii:
|
||||
const char ESC = (char) 27;
|
||||
const char ESC = (char)27;
|
||||
var ctext = Utf8ToAsciiConverter.ToAsciiString(text, ESC);
|
||||
if (ctext.Contains(ESC) == false) text = ctext;
|
||||
break;
|
||||
@@ -568,8 +568,8 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
|
||||
// apply post-filter
|
||||
if (config.PostFilter != null)
|
||||
text = config.PostFilter(text);
|
||||
|
||||
text = config.PostFilter(text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -839,7 +839,7 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
{
|
||||
term = term.Substring(i);
|
||||
term.CopyTo(0, output, opos, term.Length);
|
||||
opos += term.Length;
|
||||
opos += term.Length;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -914,21 +914,22 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// <returns>The filtered string.</returns>
|
||||
public virtual string ReplaceMany(string text, IDictionary<string, string> replacements)
|
||||
{
|
||||
// be safe
|
||||
if (text == null)
|
||||
{
|
||||
throw new ArgumentNullException("text");
|
||||
}
|
||||
|
||||
if (replacements == null)
|
||||
{
|
||||
throw new ArgumentNullException("replacements");
|
||||
}
|
||||
|
||||
// Have done various tests, implementing my own "super fast" state machine to handle
|
||||
// replacement of many items, or via regexes, but on short strings and not too
|
||||
// many replacements (which prob. is going to be our case) nothing can beat this...
|
||||
// (at least with safe and checked code -- we don't want unsafe/unchecked here)
|
||||
foreach (KeyValuePair<string, string> item in replacements)
|
||||
{
|
||||
text = text.Replace(item.Key, item.Value);
|
||||
}
|
||||
|
||||
// Note that it will do chained-replacements ie replaced items can be replaced
|
||||
// in turn by another replacement (ie the order of replacements is important)
|
||||
|
||||
return replacements.Aggregate(text, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
|
||||
return text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -940,15 +941,22 @@ function validateSafeAlias(input, value, immediate, callback) {{
|
||||
/// <returns>The filtered string.</returns>
|
||||
public virtual string ReplaceMany(string text, char[] chars, char replacement)
|
||||
{
|
||||
// be safe
|
||||
if (text == null)
|
||||
{
|
||||
throw new ArgumentNullException("text");
|
||||
}
|
||||
|
||||
if (chars == null)
|
||||
{
|
||||
throw new ArgumentNullException("chars");
|
||||
}
|
||||
|
||||
// see note above
|
||||
for (int i = 0; i < chars.Length; i++)
|
||||
{
|
||||
text = text.Replace(chars[i], replacement);
|
||||
}
|
||||
|
||||
return chars.Aggregate(text, (current, c) => current.Replace(c, replacement));
|
||||
return text;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Umbraco.Core.Sync
|
||||
if (newApplicationUrl)
|
||||
{
|
||||
appContext._umbracoApplicationDomains.Add(applicationUrl);
|
||||
LogHelper.Info(typeof(ApplicationUrlHelper), $"New ApplicationUrl detected: {applicationUrl}");
|
||||
LogHelper.Info(typeof(ApplicationUrlHelper), string.Format("New ApplicationUrl detected: {0}", applicationUrl));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,4 +169,4 @@ namespace Umbraco.Core.Sync
|
||||
return url.TrimEnd('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
|
||||
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
@@ -1547,6 +1547,7 @@
|
||||
<Compile Include="ReadLock.cs" />
|
||||
<Compile Include="TypeFinder.cs" />
|
||||
<Compile Include="TypeHelper.cs" />
|
||||
<Compile Include="Collections\CompositeTypeTypeKey.cs" />
|
||||
<Compile Include="Udi.cs" />
|
||||
<Compile Include="UdiDefinitionAttribute.cs" />
|
||||
<Compile Include="UdiEntityType.cs" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.9.4" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
|
||||
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net45" />
|
||||
|
||||
@@ -3,43 +3,24 @@ using System.Collections.Generic;
|
||||
using System.Data.SqlServerCe;
|
||||
using System.IO;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnostics.Windows;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Migrations.Initial;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Tests.Benchmarks.Config;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using ILogger = Umbraco.Core.Logging.ILogger;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[Config(typeof(Config))]
|
||||
[QuickRunWithMemoryDiagnoserConfig]
|
||||
public class BulkInsertBenchmarks
|
||||
{
|
||||
private class Config : ManualConfig
|
||||
{
|
||||
public Config()
|
||||
{
|
||||
Add(new MemoryDiagnoser());
|
||||
//Add(ExecutionValidator.FailOnError);
|
||||
|
||||
//The 'quick and dirty' settings, so it runs a little quicker
|
||||
// see benchmarkdotnet FAQ
|
||||
Add(Job.Default
|
||||
.WithLaunchCount(1) // benchmark process will be launched only once
|
||||
.WithIterationTime(100) // 100ms per iteration
|
||||
.WithWarmupCount(3) // 3 warmup iteration
|
||||
.WithTargetCount(3)); // 3 target iteration
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] _initDbBytes = null;
|
||||
|
||||
[Setup]
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var logger = new DebugDiagnosticsLogger();
|
||||
@@ -51,8 +32,8 @@ namespace Umbraco.Tests.Benchmarks
|
||||
SetupSqlCe(path, logger);
|
||||
SetupSqlServer(logger);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetupSqlServer(ILogger logger)
|
||||
{
|
||||
@@ -75,7 +56,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
[lastNotifiedDate] [datetime] NOT NULL,
|
||||
[isActive] [bit] NOT NULL,
|
||||
[isMaster] [bit] NOT NULL,
|
||||
CONSTRAINT [PK_umbracoServer] PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT [PK_umbracoServer] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[id] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||
@@ -87,7 +68,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
var dbName = string.Concat("Umb", Guid.NewGuid(), ".sdf");
|
||||
AppDomain.CurrentDomain.SetData("DataDirectory", path);
|
||||
var sqlCeConnectionString = $"Datasource=|DataDirectory|\\{dbName};Flush Interval=1;";
|
||||
|
||||
|
||||
_dbFile = Path.Combine(path, dbName);
|
||||
|
||||
//only create the db one time
|
||||
@@ -107,12 +88,12 @@ namespace Umbraco.Tests.Benchmarks
|
||||
var creation = new DatabaseSchemaCreation(_dbSqlCe, logger, _sqlCeSyntax);
|
||||
creation.InitializeDatabaseSchema();
|
||||
}
|
||||
_initDbBytes = File.ReadAllBytes(_dbFile);
|
||||
_initDbBytes = File.ReadAllBytes(_dbFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllBytes(_dbFile, _initDbBytes);
|
||||
}
|
||||
}
|
||||
|
||||
//create the db
|
||||
_dbSqlCe = new UmbracoDatabase(
|
||||
@@ -138,7 +119,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
return data;
|
||||
}
|
||||
|
||||
[Cleanup]
|
||||
[GlobalCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_dbSqlCe.Dispose();
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Collections;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class ConcurrentDictionaryBenchmarks
|
||||
{
|
||||
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, bool> AssignableTypeCache = new ConcurrentDictionary<CompositeTypeTypeKey, bool>();
|
||||
|
||||
private static object input = new Bar();
|
||||
|
||||
private static Type source = typeof(Bar);
|
||||
|
||||
private static Type target = typeof(Foo);
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public bool GetCachedCanAssignFactory()
|
||||
{
|
||||
return AssignableTypeCache.GetOrAdd(new CompositeTypeTypeKey(source, target), k =>
|
||||
{
|
||||
var ksource = k.Type1;
|
||||
var ktarget = k.Type2;
|
||||
|
||||
return ktarget.IsAssignableFrom(ksource) && typeof(IConvertible).IsAssignableFrom(ksource);
|
||||
});
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public bool GetCachedCanAssignNoFactory()
|
||||
{
|
||||
// This method is 10% faster
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
bool canConvert;
|
||||
if (AssignableTypeCache.TryGetValue(key, out canConvert))
|
||||
{
|
||||
return canConvert;
|
||||
}
|
||||
|
||||
// "is" is faster than "IsAssignableFrom"
|
||||
if (input is IConvertible && target.IsAssignableFrom(source))
|
||||
{
|
||||
return AssignableTypeCache[key] = true;
|
||||
}
|
||||
|
||||
return AssignableTypeCache[key] = false;
|
||||
}
|
||||
|
||||
private class Foo : IConvertible
|
||||
{
|
||||
public TypeCode GetTypeCode()
|
||||
{
|
||||
return TypeCode.Object;
|
||||
}
|
||||
|
||||
public bool ToBoolean(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public byte ToByte(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public char ToChar(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DateTime ToDateTime(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public decimal ToDecimal(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public double ToDouble(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public short ToInt16(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int ToInt32(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long ToInt64(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public sbyte ToSByte(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public float ToSingle(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string ToString(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object ToType(Type conversionType, IFormatProvider provider)
|
||||
{
|
||||
if (conversionType == typeof(Foo))
|
||||
{
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ushort ToUInt16(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public uint ToUInt32(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ulong ToUInt64(IFormatProvider provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class Bar : Foo
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Horology;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark.
|
||||
/// </summary>
|
||||
public class QuickRunConfigAttribute : Attribute, IConfigSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QuickRunConfigAttribute"/> class.
|
||||
/// </summary>
|
||||
public QuickRunConfigAttribute()
|
||||
{
|
||||
Config = (ManualConfig) ManualConfig.CreateEmpty()
|
||||
.With(Job.Default.WithLaunchCount(1) // benchmark process will be launched only once
|
||||
.WithIterationTime(new TimeInterval(100, TimeUnit.Millisecond)) // 100ms per iteration
|
||||
.WithWarmupCount(3) // 3 warmup iteration
|
||||
.WithTargetCount(3)); // 3 target iteration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the manual configuration.
|
||||
/// </summary>
|
||||
protected ManualConfig Config { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
IConfig IConfigSource.Config => Config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the benchmark to run with less warmup and a shorter iteration time than the standard benchmark,
|
||||
/// and include memory usage diagnosis.
|
||||
/// </summary>
|
||||
public class QuickRunWithMemoryDiagnoserConfigAttribute : QuickRunConfigAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QuickRunWithMemoryDiagnoserConfigAttribute"/> class.
|
||||
/// </summary>
|
||||
public QuickRunWithMemoryDiagnoserConfigAttribute()
|
||||
{
|
||||
Config.Add(new MemoryDiagnoser());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnostics.Windows;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
/// <summary>
|
||||
/// Want to check what is faster OfType or Cast when a enurable all has the same items
|
||||
/// </summary>
|
||||
[Config(typeof(Config))]
|
||||
[MemoryDiagnoser]
|
||||
public class LinqCastBenchmarks
|
||||
{
|
||||
private class Config : ManualConfig
|
||||
{
|
||||
public Config()
|
||||
{
|
||||
Add(new MemoryDiagnoser());
|
||||
}
|
||||
}
|
||||
|
||||
public LinqCastBenchmarks()
|
||||
{
|
||||
_array = new List<object>();
|
||||
|
||||
@@ -1,47 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlServerCe;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Columns;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnosers;
|
||||
using BenchmarkDotNet.Diagnostics.Windows;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Reports;
|
||||
using BenchmarkDotNet.Running;
|
||||
using BenchmarkDotNet.Validators;
|
||||
using Moq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.Migrations.Initial;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using ILogger = Umbraco.Core.Logging.ILogger;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[Config(typeof(Config))]
|
||||
[MemoryDiagnoser]
|
||||
public class ModelToSqlExpressionHelperBenchmarks
|
||||
{
|
||||
private class Config : ManualConfig
|
||||
{
|
||||
public Config()
|
||||
{
|
||||
Add(new MemoryDiagnoser());
|
||||
}
|
||||
}
|
||||
|
||||
public ModelToSqlExpressionHelperBenchmarks()
|
||||
{
|
||||
var contentMapper = new ContentMapper(_syntaxProvider);
|
||||
@@ -51,7 +23,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
mappingResolver.Setup(resolver => resolver.ResolveMapperByType(It.IsAny<Type>())).Returns(contentMapper);
|
||||
_mappingResolver = mappingResolver.Object;
|
||||
}
|
||||
|
||||
|
||||
private readonly ISqlSyntaxProvider _syntaxProvider = new SqlCeSyntaxProvider();
|
||||
private readonly CachedExpression _cachedExpression;
|
||||
private readonly MappingResolver _mappingResolver;
|
||||
@@ -62,18 +34,15 @@ namespace Umbraco.Tests.Benchmarks
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var a = i;
|
||||
var b = i*10;
|
||||
var b = i * 10;
|
||||
Expression<Func<IContent, bool>> predicate = content =>
|
||||
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
|
||||
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
|
||||
var result = modelToSqlExpressionHelper.Visit(predicate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Benchmark()]
|
||||
public void WithCachedExpression()
|
||||
{
|
||||
@@ -83,7 +52,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
var b = i * 10;
|
||||
Expression<Func<IContent, bool>> predicate = content =>
|
||||
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
|
||||
|
||||
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
|
||||
|
||||
//wrap it!
|
||||
@@ -92,6 +61,5 @@ namespace Umbraco.Tests.Benchmarks
|
||||
var result = modelToSqlExpressionHelper.Visit(_cachedExpression);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var switcher = new BenchmarkSwitcher(new[]
|
||||
{
|
||||
typeof(BulkInsertBenchmarks),
|
||||
typeof(ModelToSqlExpressionHelperBenchmarks),
|
||||
typeof(XmlBenchmarks),
|
||||
typeof(LinqCastBenchmarks),
|
||||
//typeof(DeepCloneBenchmarks),
|
||||
typeof(XmlPublishedContentInitBenchmarks),
|
||||
|
||||
});
|
||||
switcher.Run(args);
|
||||
new BenchmarkSwitcher(typeof(Program).Assembly).Run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Tests.Benchmarks.Config;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[QuickRunWithMemoryDiagnoserConfig]
|
||||
public class StringReplaceManyBenchmarks
|
||||
{
|
||||
/*
|
||||
|
||||
short text, short replacement:
|
||||
|
||||
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
|
||||
--------------------------------------------- |---------:|----------:|----------:|-------:|---------:|-------:|----------:|
|
||||
'String.ReplaceMany w/chars - Aggregate' | 236.0 ns | 40.92 ns | 2.312 ns | 1.00 | 0.00 | 0.0461 | 200 B |
|
||||
'String.ReplaceMany w/chars - For Loop' | 166.7 ns | 70.51 ns | 3.984 ns | 0.71 | 0.01 | 0.0420 | 180 B |
|
||||
'String.ReplaceMany w/dictionary - Aggregate' | 606.5 ns | 342.94 ns | 19.377 ns | 2.57 | 0.07 | 0.0473 | 212 B |
|
||||
'String.ReplaceMany w/dictionary - For Each' | 571.8 ns | 232.33 ns | 13.127 ns | 2.42 | 0.05 | 0.0458 | 212 B |
|
||||
|
||||
long text, short replacement:
|
||||
|
||||
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
|
||||
--------------------------------------------- |----------:|----------:|----------:|-------:|---------:|-------:|----------:|
|
||||
'String.ReplaceMany w/chars - Aggregate' | 5.771 us | 9.963 us | 0.5630 us | 1.00 | 0.00 | 1.6798 | 6.94 KB |
|
||||
'String.ReplaceMany w/chars - For Loop' | 4.962 us | 2.121 us | 0.1199 us | 0.87 | 0.08 | 1.6840 | 6.92 KB |
|
||||
'String.ReplaceMany w/dictionary - Aggregate' | 14.514 us | 8.189 us | 0.4627 us | 2.53 | 0.22 | 1.6447 | 6.96 KB |
|
||||
'String.ReplaceMany w/dictionary - For Each' | 15.445 us | 24.745 us | 1.3981 us | 2.69 | 0.30 | 1.5696 | 6.96 KB |
|
||||
|
||||
short text, long replacements dictionary:
|
||||
|
||||
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
|
||||
--------------------------------------------- |-----------:|-----------:|----------:|-------:|---------:|-------:|----------:|
|
||||
'String.ReplaceMany w/chars - Aggregate' | 257.0 ns | 200.0 ns | 11.30 ns | 1.00 | 0.00 | 0.0452 | 200 B |
|
||||
'String.ReplaceMany w/chars - For Loop' | 182.4 ns | 221.0 ns | 12.49 ns | 0.71 | 0.05 | 0.0425 | 180 B |
|
||||
'String.ReplaceMany w/dictionary - Aggregate' | 7,273.8 ns | 2,747.1 ns | 155.22 ns | 28.34 | 1.12 | 0.0714 | 464 B |
|
||||
'String.ReplaceMany w/dictionary - For Each' | 6,981.0 ns | 5,500.7 ns | 310.80 ns | 27.20 | 1.38 | 0.0775 | 464 B |
|
||||
|
||||
long text, long replacements dictionary:
|
||||
|
||||
Method | Mean | Error | StdDev | Scaled | ScaledSD | Gen 0 | Allocated |
|
||||
--------------------------------------------- |-----------:|-----------:|-----------:|-------:|---------:|-------:|----------:|
|
||||
'String.ReplaceMany w/chars - Aggregate' | 4.868 us | 3.420 us | 0.1932 us | 1.00 | 0.00 | 1.6816 | 6.94 KB |
|
||||
'String.ReplaceMany w/chars - For Loop' | 4.958 us | 2.633 us | 0.1487 us | 1.02 | 0.04 | 1.6791 | 6.92 KB |
|
||||
'String.ReplaceMany w/dictionary - Aggregate' | 181.309 us | 210.177 us | 11.8754 us | 37.29 | 2.32 | 5.3571 | 24.28 KB |
|
||||
'String.ReplaceMany w/dictionary - For Each' | 174.567 us | 113.733 us | 6.4262 us | 35.90 | 1.57 | 5.8594 | 24.28 KB |
|
||||
|
||||
*/
|
||||
|
||||
// don't use constants
|
||||
// ReSharper disable ConvertToConstant.Local
|
||||
|
||||
// input text for ReplaceMany
|
||||
private static readonly string Text;
|
||||
|
||||
// replaced chars for ReplaceMany with chars
|
||||
private static readonly char[] ReplacedChars = { ',', '.', ':', '&', '#' };
|
||||
|
||||
// replacement char for ReplaceMany with chars
|
||||
private static readonly char ReplacementChar = '*';
|
||||
|
||||
// replacements for ReplaceMany with dictionary
|
||||
private static readonly IDictionary<string, string> Replacements;
|
||||
|
||||
// ReSharper restore ConvertToConstant.Local
|
||||
|
||||
static StringReplaceManyBenchmarks()
|
||||
{
|
||||
// pick what you want to benchmark
|
||||
|
||||
// short
|
||||
Text = "1,2.3:4&5#6";
|
||||
|
||||
// long
|
||||
//Text = "Sed ut perspiciatis unde omnis iste natus &error sit voluptatem accusantium doloremque l:audantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et &quasi architecto beatae vitae ::dicta sunt explicabo. Nemo enim ipsam volupta:tem quia voluptas sit aspernatur aut o&dit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciun&t. Neque porro quisquam est, qui dolorem: ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut e:nim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi co&&nsequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse: quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?";
|
||||
|
||||
// short
|
||||
Replacements = new Dictionary<string, string>
|
||||
{
|
||||
{ ",", "*" },
|
||||
{ ".", "*" },
|
||||
{ ":", "*" },
|
||||
{ "&", "*" },
|
||||
{ "#", "*" },
|
||||
};
|
||||
|
||||
// long
|
||||
//Replacements = new Dictionary<string, string>();
|
||||
//for (var i = 2; i < 100; i++)
|
||||
// Replacements[Convert.ToChar(i).ToString()] = "*";
|
||||
}
|
||||
|
||||
// this is what v7 originally did
|
||||
[Benchmark(Description = "String.ReplaceMany w/chars - Aggregate", Baseline = true)]
|
||||
public string ReplaceManyAggregate()
|
||||
{
|
||||
var result = Text;
|
||||
return ReplacedChars.Aggregate(result, (current, c) => current.Replace(c, ReplacementChar));
|
||||
}
|
||||
|
||||
[Benchmark(Description = "String.ReplaceMany w/chars - For Loop")]
|
||||
public string ReplaceManyForLoop()
|
||||
{
|
||||
var result = Text;
|
||||
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
// ReSharper disable once ForCanBeConvertedToForeach
|
||||
for (var i = 0; i < ReplacedChars.Length; i++)
|
||||
{
|
||||
result = result.Replace(ReplacedChars[i], ReplacementChar);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// this is what v7 originally did
|
||||
[Benchmark(Description = "String.ReplaceMany w/dictionary - Aggregate")]
|
||||
public string ReplaceManyDictionaryAggregate()
|
||||
{
|
||||
return Replacements.Aggregate(Text, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
|
||||
}
|
||||
|
||||
[Benchmark(Description = "String.ReplaceMany w/dictionary - For Each")]
|
||||
public string ReplaceManyDictionaryForEach()
|
||||
{
|
||||
var result = Text;
|
||||
// ReSharper disable once LoopCanBeConvertedToQuery
|
||||
foreach (var item in Replacements)
|
||||
{
|
||||
result = result.Replace(item.Key, item.Value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
public class TryConvertToBenchmarks
|
||||
{
|
||||
private static readonly List<string> List = new List<string>() { "hello", "world", "awesome" };
|
||||
private static readonly string Date = "Saturday 10, November 2012";
|
||||
|
||||
[Benchmark(Description = "List<string> to IEnumerable<string>")]
|
||||
public IEnumerable<string> TryConvertToEnumerable()
|
||||
{
|
||||
return List.TryConvertTo<IEnumerable<string>>().Result;
|
||||
}
|
||||
|
||||
[Benchmark(Description = "Int to Double")]
|
||||
public double TryConvertToDouble()
|
||||
{
|
||||
return 1.TryConvertTo<double>().Result;
|
||||
}
|
||||
|
||||
[Benchmark(Description = "Float to Decimal")]
|
||||
public decimal TryConvertToDecimal()
|
||||
{
|
||||
return 1F.TryConvertTo<decimal>().Result;
|
||||
}
|
||||
|
||||
[Benchmark(Description = "String to Boolean")]
|
||||
public bool TryConvertToBoolean()
|
||||
{
|
||||
return "1".TryConvertTo<bool>().Result;
|
||||
}
|
||||
|
||||
[Benchmark(Description = "String to DateTime")]
|
||||
public DateTime TryConvertToDateTime()
|
||||
{
|
||||
return Date.TryConvertTo<DateTime>().Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,12 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Umbraco.Tests.Benchmarks</RootNamespace>
|
||||
<AssemblyName>Umbraco.Tests.Benchmarks</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<TargetFrameworkProfile />
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -38,38 +39,55 @@
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BenchmarkDotNet, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.0.9.9\lib\net45\BenchmarkDotNet.dll</HintPath>
|
||||
<Reference Include="BenchmarkDotNet, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.0.10.12\lib\net46\BenchmarkDotNet.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BenchmarkDotNet.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Core.0.9.9\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
|
||||
<Reference Include="BenchmarkDotNet.Core, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Core.0.10.12\lib\net46\BenchmarkDotNet.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BenchmarkDotNet.Diagnostics.Windows, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Diagnostics.Windows.0.9.9\lib\net45\BenchmarkDotNet.Diagnostics.Windows.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.9.9\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
|
||||
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.10.12.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.10.12\lib\net46\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
|
||||
<Reference Include="Microsoft.CodeAnalysis, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Diagnostics.Tracing.TraceEvent, Version=1.0.41.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.DotNet.InternalAbstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.DotNet.InternalAbstractions.1.0.0\lib\net451\Microsoft.DotNet.InternalAbstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.DotNet.PlatformAbstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.DotNet.PlatformAbstractions.1.1.1\lib\net451\Microsoft.DotNet.PlatformAbstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Win32.Registry, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Win32.Registry.4.3.0\lib\net46\Microsoft.Win32.Registry.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.1.1309.919, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.1.1309.0919\lib\net40\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
@@ -77,13 +95,52 @@
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Diagnostics.FileVersionInfo, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Diagnostics.StackTrace, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Reflection.Metadata, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.Metadata.1.3.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
|
||||
<Reference Include="System.Reflection.Metadata, Version=1.4.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net46\System.Security.Cryptography.Algorithms.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Text.Encoding.CodePages, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
@@ -91,20 +148,38 @@
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.XmlDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.XPath, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.XPath.XDocument, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConcurrentDictionaryBenchmarks.cs" />
|
||||
<Compile Include="Config\QuickRunConfigAttribute.cs" />
|
||||
<Compile Include="Config\QuickRunWithMemoryDiagnoserConfigAttribute.cs" />
|
||||
<Compile Include="LinqCastBenchmarks.cs" />
|
||||
<Compile Include="ModelToSqlExpressionHelperBenchmarks.cs" />
|
||||
<Compile Include="BulkInsertBenchmarks.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StringReplaceManyBenchmarks.cs" />
|
||||
<Compile Include="TryConvertToBenchmarks.cs" />
|
||||
<Compile Include="XmlBenchmarks.cs" />
|
||||
<Compile Include="XmlPublishedContentInitBenchmarks.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="_TraceEventProgrammersGuide.docx" />
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
|
||||
@@ -120,10 +195,6 @@
|
||||
<Name>Umbraco.Web</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="TraceEvent.ReadMe.txt" />
|
||||
<Content Include="TraceEvent.ReleaseNotes.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
||||
@@ -1,42 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnostics.Windows;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using Umbraco.Tests.Benchmarks.Config;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[Config(typeof(Config))]
|
||||
[QuickRunWithMemoryDiagnoserConfig]
|
||||
public class XmlBenchmarks
|
||||
{
|
||||
private class Config : ManualConfig
|
||||
{
|
||||
public Config()
|
||||
{
|
||||
Add(new MemoryDiagnoser());
|
||||
//Add(ExecutionValidator.FailOnError);
|
||||
|
||||
//The 'quick and dirty' settings, so it runs a little quicker
|
||||
// see benchmarkdotnet FAQ
|
||||
Add(Job.Default
|
||||
.WithLaunchCount(1) // benchmark process will be launched only once
|
||||
.WithIterationTime(100) // 100ms per iteration
|
||||
.WithWarmupCount(3) // 3 warmup iteration
|
||||
.WithTargetCount(3)); // 3 target iteration
|
||||
}
|
||||
}
|
||||
|
||||
[Setup]
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var templateId = 0;
|
||||
var xmlText = @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<!DOCTYPE root[
|
||||
<!DOCTYPE root[
|
||||
<!ELEMENT Home ANY>
|
||||
<!ATTLIST Home id ID #REQUIRED>
|
||||
<!ELEMENT CustomDocument ANY>
|
||||
@@ -49,7 +26,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
|
||||
<content><![CDATA[<div>This is some content</div>]]></content>
|
||||
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
|
||||
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
|
||||
<Home id=""1174"" parentID=""1173"" level=""3"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""2"" createDate=""2012-07-20T18:07:54"" updateDate=""2012-07-20T19:10:27"" nodeName=""Sub2"" urlName=""sub2"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173,1174"" isDoc="""">
|
||||
<content><![CDATA[]]></content>
|
||||
<umbracoUrlAlias><![CDATA[only/one/alias]]></umbracoUrlAlias>
|
||||
@@ -70,7 +47,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
_xml.LoadXml(xmlText);
|
||||
}
|
||||
|
||||
[Cleanup]
|
||||
[GlobalCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_xml = null;
|
||||
@@ -90,7 +67,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
public void XmlWithNavigation()
|
||||
{
|
||||
var elt = _xml.DocumentElement;
|
||||
var id = NavigateElementRoute(elt, new[] {"home", "sub1", "sub2"});
|
||||
var id = NavigateElementRoute(elt, new[] { "home", "sub1", "sub2" });
|
||||
if (id <= 0) Console.WriteLine("ERR");
|
||||
}
|
||||
|
||||
@@ -120,4 +97,4 @@ namespace Umbraco.Tests.Benchmarks
|
||||
return found ? int.Parse(elt.GetAttribute("id")) : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,37 +3,17 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Diagnostics.Windows;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Tests.Benchmarks.Config;
|
||||
using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
|
||||
namespace Umbraco.Tests.Benchmarks
|
||||
{
|
||||
[Config(typeof(Config))]
|
||||
[QuickRunWithMemoryDiagnoserConfig]
|
||||
public class XmlPublishedContentInitBenchmarks
|
||||
{
|
||||
private class Config : ManualConfig
|
||||
{
|
||||
public Config()
|
||||
{
|
||||
Add(new MemoryDiagnoser());
|
||||
|
||||
//The 'quick and dirty' settings, so it runs a little quicker
|
||||
// see benchmarkdotnet FAQ
|
||||
Add(Job.Default
|
||||
.WithLaunchCount(1) // benchmark process will be launched only once
|
||||
.WithIterationTime(100) // 100ms per iteration
|
||||
.WithWarmupCount(3) // 3 warmup iteration
|
||||
.WithTargetCount(3)); // 3 target iteration
|
||||
}
|
||||
}
|
||||
|
||||
public XmlPublishedContentInitBenchmarks()
|
||||
{
|
||||
_xml10 = Build(10);
|
||||
@@ -281,7 +261,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
var nodes = xmlNode.SelectNodes(dataXPath);
|
||||
|
||||
contentType = GetPublishedContentType(PublishedItemType.Content, docTypeAlias);
|
||||
|
||||
|
||||
var propertyNodes = new Dictionary<string, XmlNode>();
|
||||
if (nodes != null)
|
||||
foreach (XmlNode n in nodes)
|
||||
@@ -307,8 +287,8 @@ namespace Umbraco.Tests.Benchmarks
|
||||
|
||||
private static PublishedContentType GetPublishedContentType(PublishedItemType type, string alias)
|
||||
{
|
||||
return new PublishedContentType(alias, new string[] {},
|
||||
new List<PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => new PublishedPropertyType("prop" + x, 0, "test", initConverters:false))));
|
||||
return new PublishedContentType(alias, new string[] { },
|
||||
new List<PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => new PublishedPropertyType("prop" + x, 0, "test", initConverters: false))));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845dcd8080cc91" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
|
||||
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
@@ -27,6 +30,10 @@
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
@@ -36,45 +43,25 @@
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
<assemblyIdentity name="BenchmarkDotNet.Core" publicKeyToken="aa0ca2f9092cefc4" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-0.10.12.0" newVersion="0.10.12.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
|
||||
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
</configuration>
|
||||
@@ -1,40 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="BenchmarkDotNet" version="0.9.9" targetFramework="net45" />
|
||||
<package id="BenchmarkDotNet.Core" version="0.9.9" targetFramework="net45" />
|
||||
<package id="BenchmarkDotNet" version="0.10.12" targetFramework="net46" />
|
||||
<package id="BenchmarkDotNet.Core" version="0.10.12" targetFramework="net46" />
|
||||
<package id="BenchmarkDotNet.Diagnostics.Windows" version="0.9.9" targetFramework="net45" />
|
||||
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.9.9" targetFramework="net45" />
|
||||
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.10.12" targetFramework="net46" />
|
||||
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="2.4.0" targetFramework="net46" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="2.4.0" targetFramework="net46" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.TraceEvent" version="1.0.41" targetFramework="net45" />
|
||||
<package id="Microsoft.DotNet.InternalAbstractions" version="1.0.0" targetFramework="net46" />
|
||||
<package id="Microsoft.DotNet.PlatformAbstractions" version="1.1.1" targetFramework="net46" />
|
||||
<package id="Microsoft.SqlServer.Compact" version="4.0.8854.1" targetFramework="net45" />
|
||||
<package id="Microsoft.Win32.Registry" version="4.3.0" targetFramework="net46" />
|
||||
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.2.0" targetFramework="net45" />
|
||||
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Diagnostics.Tools" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Dynamic.Runtime" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Globalization" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Linq" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Linq.Expressions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Reflection" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Reflection.Metadata" version="1.3.0" targetFramework="net45" />
|
||||
<package id="System.AppContext" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Collections" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Collections.Immutable" version="1.3.1" targetFramework="net46" />
|
||||
<package id="System.Console" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Diagnostics.FileVersionInfo" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Diagnostics.StackTrace" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Dynamic.Runtime" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Globalization" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.IO.Compression" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Linq" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Reflection" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Reflection.Metadata" version="1.4.2" targetFramework="net46" />
|
||||
<package id="System.Reflection.Primitives" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Numerics" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Text.Encoding" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Text.Encoding.Extensions" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Threading" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.0.0" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks.Parallel" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Runtime" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Text.Encoding.CodePages" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading.Tasks.Parallel" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Threading.Thread" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.ValueTuple" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XPath" version="4.3.0" targetFramework="net46" />
|
||||
<package id="System.Xml.XPath.XDocument" version="4.3.0" targetFramework="net46" />
|
||||
</packages>
|
||||
@@ -161,9 +161,9 @@ namespace Umbraco.Tests
|
||||
var obj = new MyTestObject();
|
||||
var result = obj.TryConvertTo<object>();
|
||||
|
||||
Assert.AreEqual(obj, result.Result);
|
||||
Assert.AreEqual(obj, result.Result);
|
||||
}
|
||||
|
||||
|
||||
private CultureInfo savedCulture;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -332,6 +332,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
var contentType = (IContentType)MockedContentTypes.CreateSimpleContentType2("test", "Test", propertyGroupName: "testGroup");
|
||||
|
||||
Assert.AreEqual(4, contentType.PropertyTypes.Count());
|
||||
|
||||
// remove all templates - since they are not saved, they would break the (wtf) mapping code
|
||||
contentType.AllowedTemplates = new ITemplate[0];
|
||||
|
||||
// there is NO mapping from display to contentType, but only from save
|
||||
// to contentType, so if we want to test, let's to it properly!
|
||||
|
||||
@@ -24,7 +24,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[TestCase("Alpha (10)", "Alpha (2)", +1)] // this is the real stuff
|
||||
[TestCase("Kilo", "Golf (2)", +1)]
|
||||
[TestCase("Kilo (1)", "Golf (2)", +1)]
|
||||
public void ComparerTest(string name1, string name2, int expected)
|
||||
[TestCase("", "", 0)]
|
||||
[TestCase(null, null, 0)]
|
||||
public void ComparerTest(string name1, string name2, int expected)
|
||||
{
|
||||
var comparer = new SimilarNodeName.Comparer();
|
||||
|
||||
@@ -76,7 +78,9 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[TestCase(0, "Alpha", "Alpha (3)")]
|
||||
[TestCase(0, "Kilo (1)", "Kilo (1) (1)")] // though... we might consider "Kilo (2)"
|
||||
[TestCase(6, "Kilo (1)", "Kilo (1)")] // because of the id
|
||||
public void Test(int nodeId, string nodeName, string expected)
|
||||
[TestCase(0, "", " (1)")]
|
||||
[TestCase(0, null, " (1)")]
|
||||
public void Test(int nodeId, string nodeName, string expected)
|
||||
{
|
||||
var names = new[]
|
||||
{
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 440 KiB After Width: | Height: | Size: 386 KiB |
+185
@@ -1,3 +1,188 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTour
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco 7.8</b>. The tour component is a global component and is already added to the umbraco markup.
|
||||
In the Umbraco UI the tours live in the "Help drawer" which opens when you click the Help-icon in the bottom left corner of Umbraco.
|
||||
You can easily add you own tours to the Help-drawer or show and start tours from
|
||||
anywhere in the Umbraco backoffice. To see a real world example of a custom tour implementation, install <a href="https://our.umbraco.org/projects/starter-kits/the-starter-kit/">The Starter Kit</a> in Umbraco 7.8
|
||||
|
||||
<h1><b>Extending the help drawer with custom tours</b></h1>
|
||||
The easiet way to add new tours to Umbraco is through the Help-drawer. All it requires is a my-tour.json file.
|
||||
Place the file in <i>App_Plugins/{MyPackage}/backoffice/tours/{my-tour}.json</i> and it will automatically be
|
||||
picked up by Umbraco and shown in the Help-drawer.
|
||||
|
||||
<h3><b>The tour object</b></h3>
|
||||
The tour object consist of two parts - The overall tour configuration and a list of tour steps. We have split up the tour object for a better overview.
|
||||
<pre>
|
||||
// The tour config object
|
||||
{
|
||||
"name": "My Custom Tour", // (required)
|
||||
"alias": "myCustomTour", // A unique tour alias (required)
|
||||
"group": "My Custom Group" // Used to group tours in the help drawer
|
||||
"groupOrder": 200 // Control the order of tour groups
|
||||
"allowDisable": // Adds a "Don't" show this tour again"-button to the intro step
|
||||
"requiredSections":["content", "media", "mySection"] // Sections that the tour will access while running, if the user does not have access to the required tour sections, the tour will not load.
|
||||
"steps": [] // tour steps - see next example
|
||||
}
|
||||
</pre>
|
||||
<pre>
|
||||
// A tour step object
|
||||
{
|
||||
"title": "Title",
|
||||
"content": "<p>Step content</p>",
|
||||
"type": "intro" // makes the step an introduction step,
|
||||
"element": "[data-element='my-table-row']", // the highlighted element
|
||||
"event": "click" // forces the user to click the UI to go to next step
|
||||
"eventElement": "[data-element='my-table-row'] [data-element='my-tour-button']" // specify an element to click inside a highlighted element
|
||||
"elementPreventClick": false // prevents user interaction in the highlighted element
|
||||
"backdropOpacity": 0.4 // the backdrop opacity
|
||||
"view": "" // add a custom view
|
||||
"customProperties" : {} // add any custom properties needed for the custom view
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h1><b>Adding tours to other parts of the Umbraco backoffice</b></h1>
|
||||
It is also possible to add a list of custom tours to other parts of the Umbraco backoffice,
|
||||
as an example on a Dashboard in a Custom section. You can then use the {@link umbraco.services.tourService tourService} to start and stop tours but you don't have to register them as part of the tour service.
|
||||
|
||||
<h1><b>Using the tour service</b></h1>
|
||||
<h3>Markup example - show custom tour</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.TourController as vm">
|
||||
|
||||
<div>{{vm.tour.name}}</div>
|
||||
<button type="button" ng-click="vm.startTour()">Start tour</button>
|
||||
|
||||
<!-- This button will be clicked in the tour -->
|
||||
<button data-element="my-tour-button" type="button">Click me</button>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example - show custom tour</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function TourController(tourService) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.tour = {
|
||||
"name": "My Custom Tour",
|
||||
"alias": "myCustomTour",
|
||||
"steps": [
|
||||
{
|
||||
"title": "Welcome to My Custom Tour",
|
||||
"content": "",
|
||||
"type": "intro"
|
||||
},
|
||||
{
|
||||
"element": "[data-element='my-tour-button']",
|
||||
"title": "Click the button",
|
||||
"content": "Click the button",
|
||||
"event": "click"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
vm.startTour = startTour;
|
||||
|
||||
function startTour() {
|
||||
tourService.startTour(vm.tour);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.TourController", TourController);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
<h1><b>Custom step views</b></h1>
|
||||
In some cases you will need a custom view for one of your tour steps.
|
||||
This could be for validation or for running any other custom logic for that step.
|
||||
We have added a couple of helper components to make it easier to get the step scaffolding to look like a regular tour step.
|
||||
In the following example you see how to run some custom logic before a step goes to the next step.
|
||||
|
||||
<h3>Markup example - custom step view</h3>
|
||||
<pre>
|
||||
<div ng-controller="My.TourStep as vm">
|
||||
|
||||
<umb-tour-step on-close="model.endTour()">
|
||||
|
||||
<umb-tour-step-header
|
||||
title="model.currentStep.title">
|
||||
</umb-tour-step-header>
|
||||
|
||||
<umb-tour-step-content
|
||||
content="model.currentStep.content">
|
||||
|
||||
<!-- Add any custom content here -->
|
||||
|
||||
</umb-tour-step-content>
|
||||
|
||||
<umb-tour-step-footer class="flex justify-between items-center">
|
||||
|
||||
<umb-tour-step-counter
|
||||
current-step="model.currentStepIndex + 1"
|
||||
total-steps="model.steps.length">
|
||||
</umb-tour-step-counter>
|
||||
|
||||
<div>
|
||||
<umb-button
|
||||
size="xs"
|
||||
button-style="success"
|
||||
type="button"
|
||||
action="vm.initNextStep()"
|
||||
label="Next">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
</umb-tour-step-footer>
|
||||
|
||||
</umb-tour-step>
|
||||
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
<h3>Controller example - custom step view</h3>
|
||||
<pre>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function StepController() {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.initNextStep = initNextStep;
|
||||
|
||||
function initNextStep() {
|
||||
// run logic here before going to the next step
|
||||
$scope.model.nextStep();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("My.TourStep", StepController);
|
||||
|
||||
})();
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Related services</h3>
|
||||
<ul>
|
||||
<li>{@link umbraco.services.tourService tourService}</li>
|
||||
</ul>
|
||||
|
||||
@param {string} model (<code>binding</code>): Tour object
|
||||
|
||||
**/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -215,6 +215,8 @@
|
||||
|
||||
$scope.page.buttonGroupState = "success";
|
||||
|
||||
}, function(err) {
|
||||
$scope.page.buttonGroupState = 'error';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -30,80 +30,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.tourService#registerTour
|
||||
* @methodOf umbraco.services.tourService
|
||||
*
|
||||
* @description
|
||||
* Registers a tour in the service
|
||||
* @param {Object} tour The tour you want to register in the service
|
||||
* @param {String} tour.name The tour name
|
||||
* @param {String} tour.alias The tour alias
|
||||
* @param {Array} tour.steps Array of tour steps
|
||||
* @param {String} tour.step.title Step title
|
||||
* @param {DomElement} tour.step.content Step content (pass in any HTML markup)
|
||||
* @param {DomElement} tour.step.element Highlight a DOM-element
|
||||
* @param {Boolean} tour.step.elementPreventClick Adds invisible layer on top of highligted element to prevent all clicks and interaction with it
|
||||
* @param {Number} tour.step.backdropOpacity Sets the backdrop opacity (default 0.4)
|
||||
*/
|
||||
function registerTour(newTour) {
|
||||
validateTour(newTour);
|
||||
validateTourRegistration(newTour);
|
||||
tours.push(newTour);
|
||||
eventsService.emit("appState.tour.updatedTours", tours);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.tourService#registerTours
|
||||
* @methodOf umbraco.services.tourService
|
||||
*
|
||||
* @description
|
||||
* Registers an array of tours in the service
|
||||
* @param {Array} tours The tours to register in the service
|
||||
*/
|
||||
function registerTours(newTours) {
|
||||
angular.forEach(newTours, function(newTour){
|
||||
validateTour(newTour);
|
||||
validateTourRegistration(newTour);
|
||||
tours.push(newTour);
|
||||
});
|
||||
eventsService.emit("appState.tour.updatedTours", tours);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.tourService#unregisterTour
|
||||
* @methodOf umbraco.services.tourService
|
||||
*
|
||||
* @description
|
||||
* Unregisters a tour in the service
|
||||
* @param {String} tourAlias The tour alias of the tour you want to unregister
|
||||
*/
|
||||
function unregisterTour(tourAlias) {
|
||||
tours = tours.filter(function( obj ) {
|
||||
return obj.alias !== tourAlias;
|
||||
});
|
||||
eventsService.emit("appState.tour.updatedTours", tours);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.tourService#unregisterTourGroup
|
||||
* @methodOf umbraco.services.tourService
|
||||
*
|
||||
* @description
|
||||
* Unregisters a tour in the service
|
||||
* @param {String} tourGroupName The name of the tour group you want to unregister
|
||||
*/
|
||||
function unregisterTourGroup(tourGroup) {
|
||||
tours = tours.filter(function( obj ) {
|
||||
return obj.group !== tourGroup;
|
||||
});
|
||||
eventsService.emit("appState.tour.updatedTours", tours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return all of the tours as a new instance
|
||||
*/
|
||||
@@ -286,6 +212,9 @@
|
||||
throw "Tour " + tour.alias + " is missing tour steps";
|
||||
}
|
||||
|
||||
if (tour.requiredSections.length === 0) {
|
||||
throw "Tour " + tour.alias + " is missing the required sections";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,10 +263,6 @@
|
||||
|
||||
var service = {
|
||||
registerAllTours: registerAllTours,
|
||||
registerTour: registerTour,
|
||||
registerTours: registerTours,
|
||||
unregisterTour: unregisterTour,
|
||||
unregisterTourGroup: unregisterTourGroup,
|
||||
startTour: startTour,
|
||||
endTour: endTour,
|
||||
disableTour: disableTour,
|
||||
@@ -353,4 +278,4 @@
|
||||
|
||||
angular.module("umbraco.services").factory("tourService", tourService);
|
||||
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -14,7 +14,6 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
$scope.isSearching = false;
|
||||
$scope.selectedResult = -1;
|
||||
|
||||
|
||||
$scope.navigateResults = function (ev) {
|
||||
//38: up 40: down, 13: enter
|
||||
|
||||
@@ -34,24 +33,37 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var group = undefined;
|
||||
var groupNames = [];
|
||||
var groupIndex = -1;
|
||||
var itemIndex = -1;
|
||||
$scope.selectedItem = undefined;
|
||||
|
||||
|
||||
$scope.clearSearch = function () {
|
||||
$scope.searchTerm = null;
|
||||
};
|
||||
function iterateResults(up) {
|
||||
//default group
|
||||
if (!group) {
|
||||
group = $scope.groups[0];
|
||||
|
||||
for (var g in $scope.groups) {
|
||||
if ($scope.groups.hasOwnProperty(g)) {
|
||||
groupNames.push(g);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Sorting to match the groups order
|
||||
groupNames.sort();
|
||||
|
||||
group = $scope.groups[groupNames[0]];
|
||||
groupIndex = 0;
|
||||
}
|
||||
|
||||
if (up) {
|
||||
if (itemIndex === 0) {
|
||||
if (groupIndex === 0) {
|
||||
gotoGroup($scope.groups.length - 1, true);
|
||||
gotoGroup(Object.keys($scope.groups).length - 1, true);
|
||||
} else {
|
||||
gotoGroup(groupIndex - 1, true);
|
||||
}
|
||||
@@ -62,7 +74,7 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
if (itemIndex < group.results.length - 1) {
|
||||
gotoItem(itemIndex + 1);
|
||||
} else {
|
||||
if (groupIndex === $scope.groups.length - 1) {
|
||||
if (groupIndex === Object.keys($scope.groups).length - 1) {
|
||||
gotoGroup(0);
|
||||
} else {
|
||||
gotoGroup(groupIndex + 1);
|
||||
@@ -73,7 +85,7 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
|
||||
function gotoGroup(index, up) {
|
||||
groupIndex = index;
|
||||
group = $scope.groups[groupIndex];
|
||||
group = $scope.groups[groupNames[groupIndex]];
|
||||
|
||||
if (up) {
|
||||
gotoItem(group.results.length - 1);
|
||||
@@ -95,6 +107,13 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
$scope.hasResults = false;
|
||||
if ($scope.searchTerm) {
|
||||
if (newVal !== null && newVal !== undefined && newVal !== oldVal) {
|
||||
|
||||
//Resetting for brand new search
|
||||
group = undefined;
|
||||
groupNames = [];
|
||||
groupIndex = -1;
|
||||
itemIndex = -1;
|
||||
|
||||
$scope.isSearching = true;
|
||||
navigationService.showSearch();
|
||||
$scope.selectedItem = undefined;
|
||||
@@ -114,7 +133,7 @@ function SearchController($scope, searchService, $log, $location, navigationServ
|
||||
var filtered = {};
|
||||
_.each(result, function (value, key) {
|
||||
if (value.results.length > 0) {
|
||||
filtered[key] = value;
|
||||
filtered[key] = value;
|
||||
}
|
||||
});
|
||||
$scope.groups = filtered;
|
||||
|
||||
@@ -20,8 +20,17 @@ app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navi
|
||||
assetsService._loadInitAssets().then(function() {
|
||||
|
||||
//Register all of the tours on the server
|
||||
tourService.registerAllTours().then(function (dashboards) {
|
||||
tourService.registerAllTours().then(function () {
|
||||
appReady(data);
|
||||
|
||||
// Auto start intro tour
|
||||
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
|
||||
// start intro tour if it hasn't been completed or disabled
|
||||
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
|
||||
tourService.startTour(introTour);
|
||||
}
|
||||
});
|
||||
|
||||
}, function(){
|
||||
appReady(data);
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="email">Email</label>
|
||||
<div class="controls">
|
||||
<input type="email" id="email" name="email" placeholder="you@example.com" required ng-model="installer.current.model.email" val-email />
|
||||
<input type="email" id="email" name="email" placeholder="you@example.com" val-email required ng-model="installer.current.model.email" />
|
||||
<small class="inline-help">Your email will be used as your login</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
.umb-tree .umb-tree-node-checked i:before {
|
||||
/*check box*/
|
||||
content: "\e165" !important;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
a.umb-options {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<form novalidate name="insertMacroForm" ng-submit="submitForm()" ng-controller="Umbraco.Dialogs.InsertMacroController" val-form-manager>
|
||||
<form novalidate name="insertMacroForm" ng-controller="Umbraco.Dialogs.InsertMacroController" val-form-manager>
|
||||
<div class="umb-panel">
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
@@ -6,8 +6,8 @@
|
||||
<a href class="btn btn-link" ng-click="close()">
|
||||
<localize key="cancel" />
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<localize key="buttons_select"/>
|
||||
<button type="button" ng-click="submitForm()" class="btn btn-primary">
|
||||
<localize key="buttons_select" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
vm.initNextStep = initNextStep;
|
||||
|
||||
function initNextStep() {
|
||||
if(element.val().toLowerCase() === 'my home page') {
|
||||
if(element.val().toLowerCase() === 'home page') {
|
||||
$scope.model.nextStep();
|
||||
} else {
|
||||
vm.error = true;
|
||||
|
||||
@@ -28,19 +28,10 @@ function startUpDynamicContentController($timeout, dashboardResource, assetsServ
|
||||
vm.startTour = startTour;
|
||||
|
||||
function onInit() {
|
||||
|
||||
// load tours
|
||||
tourService.getGroupedTours().then(function(groupedTours) {
|
||||
vm.tours = groupedTours;
|
||||
});
|
||||
|
||||
// get intro tour
|
||||
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
|
||||
// start intro tour if it hasn't been completed or disabled
|
||||
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
|
||||
tourService.startTour(introTour);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startTour(tour) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<a href="" ng-click="createMediaType()" umb-auto-focus>
|
||||
<i class="large icon-item-arrangement"></i>
|
||||
<span class="menu-label">
|
||||
<localize key="general_new">New</localize>
|
||||
<localize key="general_new">New</localize>
|
||||
<localize key="content_mediatype">Media type</localize>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -261,7 +261,7 @@ angular.module("umbraco")
|
||||
$scope.openEditorOverlay = function(event, area, index, key) {
|
||||
$scope.editorOverlay = {
|
||||
view: "itempicker",
|
||||
filter: false,
|
||||
filter: area.$allowedEditors.length > 15,
|
||||
title: localizationService.localize("grid_insertControl"),
|
||||
availableItems: area.$allowedEditors,
|
||||
event: event,
|
||||
@@ -860,6 +860,14 @@ angular.module("umbraco")
|
||||
gridService.getGridEditors().then(function (response) {
|
||||
$scope.availableEditors = response.data;
|
||||
|
||||
//Localize the grid editor names
|
||||
angular.forEach($scope.availableEditors, function (value, key) {
|
||||
//If no translation is provided, keep using the editor name from the manifest
|
||||
if (localizationService.dictionary.hasOwnProperty("grid_" + value.alias)) {
|
||||
value.name = localizationService.localize("grid_" + value.alias);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.contentReady = true;
|
||||
|
||||
// *********************************************
|
||||
|
||||
+10
-6
@@ -77,14 +77,14 @@ function includePropsPreValsController($rootScope, $scope, localizationService,
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, ui) {
|
||||
var h = ui.clone();
|
||||
|
||||
h.children().each(function () {
|
||||
$(this).width($(this).width());
|
||||
ui.children().each(function () {
|
||||
$(this).width($(this).width());
|
||||
});
|
||||
h.css("background-color", "lightgray");
|
||||
|
||||
return h;
|
||||
var row = ui.clone();
|
||||
row.css("background-color", "lightgray");
|
||||
|
||||
return row;
|
||||
};
|
||||
|
||||
$scope.sortableOptions = {
|
||||
@@ -96,6 +96,10 @@ function includePropsPreValsController($rootScope, $scope, localizationService,
|
||||
cursor: 'move',
|
||||
items: '> tr',
|
||||
tolerance: 'pointer',
|
||||
forcePlaceholderSize: true,
|
||||
start: function(e, ui){
|
||||
ui.placeholder.height(ui.item.height());
|
||||
},
|
||||
update: function (e, ui) {
|
||||
|
||||
// Get the new and old index for the moved element (using the text as the identifier)
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<td style="width:100px;"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody ui-sortable="sortableOptions">
|
||||
<tbody ui-sortable="sortableOptions" ng-model="model.value">
|
||||
<tr ng-repeat="val in model.value">
|
||||
<td>
|
||||
<i class="icon icon-navigation handle"></i>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
vm.disableUser = disableUser;
|
||||
vm.enableUser = enableUser;
|
||||
vm.unlockUser = unlockUser;
|
||||
vm.changeAvatar = changeAvatar;
|
||||
vm.clearAvatar = clearAvatar;
|
||||
vm.save = save;
|
||||
|
||||
@@ -356,7 +357,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
$scope.changeAvatar = function (files, event) {
|
||||
function changeAvatar(files, event) {
|
||||
if (files && files.length > 0) {
|
||||
upload(files[0]);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
<a href=""
|
||||
class="umb-user-group-preview__action"
|
||||
ngf-select ng-model="filesHolder"
|
||||
ngf-change="changeAvatar($files, $event)"
|
||||
ngf-change="model.changeAvatar($files, $event)"
|
||||
ngf-multiple="false"
|
||||
ngf-pattern="{{model.acceptedFileTypes}}"
|
||||
ngf-max-size="{{ model.maxFileSize }}">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function UsersController($scope, $timeout, $location, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
|
||||
function UsersController($scope, $timeout, $location, $routeParams, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
|
||||
|
||||
var vm = this;
|
||||
var localizeSaving = localizationService.localize("general_saving");
|
||||
@@ -124,6 +124,13 @@
|
||||
vm.usersOptions.orderBy = "Name";
|
||||
vm.usersOptions.orderDirection = "Ascending";
|
||||
|
||||
if ($routeParams.create) {
|
||||
setUsersViewState("createUser");
|
||||
}
|
||||
else if ($routeParams.invite) {
|
||||
setUsersViewState("inviteUser");
|
||||
}
|
||||
|
||||
// Get users
|
||||
getUsers();
|
||||
|
||||
@@ -168,6 +175,17 @@
|
||||
|
||||
if (state === "createUser") {
|
||||
clearAddUserForm();
|
||||
|
||||
$location.search("create", "true");
|
||||
$location.search("invite", null);
|
||||
}
|
||||
else if (state === "inviteUser") {
|
||||
$location.search("create", null);
|
||||
$location.search("invite", "true");
|
||||
}
|
||||
else if (state === "overview") {
|
||||
$location.search("create", null);
|
||||
$location.search("invite", null);
|
||||
}
|
||||
|
||||
vm.usersViewState = state;
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ClientDependency.Core, Version=1.9.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ClientDependency.1.9.4\lib\net45\ClientDependency.Core.dll</HintPath>
|
||||
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ClientDependency.Core.Mvc, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll</HintPath>
|
||||
@@ -332,8 +332,8 @@
|
||||
<Name>umbraco.providers</Name>
|
||||
</ProjectReference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.8.100, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.8\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
<Reference Include="Umbraco.ModelsBuilder, Version=3.0.10.102, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Umbraco.ModelsBuilder.3.0.10\lib\Umbraco.ModelsBuilder.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -1027,6 +1027,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<DevelopmentServerPort>7800</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7800</IISUrl>
|
||||
<DevelopmentServerPort>7800</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7800</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -848,6 +848,12 @@
|
||||
<key alias="template">Šablona</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
|
||||
@@ -830,6 +830,12 @@ Vennlig hilsen Umbraco roboten
|
||||
<key alias="template">Mal</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Sett inn element</key>
|
||||
<key alias="chooseLayout">Velg layout</key>
|
||||
<key alias="addRows">Legg til rad</key>
|
||||
|
||||
@@ -995,6 +995,12 @@
|
||||
<key alias="template">範本</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">選擇內容類別</key>
|
||||
<key alias="chooseLayout">選擇排列方式</key>
|
||||
<key alias="addRows">新增一行</key>
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
"group": "Getting Started",
|
||||
"groupOrder": 100,
|
||||
"allowDisable": true,
|
||||
"requiredSections": [
|
||||
"content",
|
||||
"media",
|
||||
"settings",
|
||||
"developer",
|
||||
"users",
|
||||
"member",
|
||||
"forms"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"title": "Welcome to Umbraco - The Friendly CMS",
|
||||
@@ -25,7 +34,6 @@
|
||||
"content": "Each area in Umbraco is called a <b>Section</b>. Right now you are in the Content section, when you want to go to another section simply click on the appropriate icon in the main menu and you'll be there in no time.",
|
||||
"backdropOpacity": 0.6
|
||||
},
|
||||
|
||||
{
|
||||
"element": "#tree",
|
||||
"elementPreventClick": true,
|
||||
@@ -88,6 +96,15 @@
|
||||
"alias": "umbIntroCreateDocType",
|
||||
"group": "Getting Started",
|
||||
"groupOrder": 100,
|
||||
"requiredSections": [
|
||||
"content",
|
||||
"media",
|
||||
"settings",
|
||||
"developer",
|
||||
"users",
|
||||
"member",
|
||||
"forms"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"title": "Create your first Document Type",
|
||||
@@ -117,7 +134,7 @@
|
||||
{
|
||||
"element": "[data-element='editor-name-field']",
|
||||
"title": "Enter a name",
|
||||
"content": "<p>Your Document Type needs a name. Enter <code>My Home Page</code> in the field and click <b>Next</b>.",
|
||||
"content": "<p>Your Document Type needs a name. Enter <code>Home Page</code> in the field and click <b>Next</b>.",
|
||||
"view": "doctypename"
|
||||
},
|
||||
{
|
||||
@@ -203,6 +220,15 @@
|
||||
"alias": "umbIntroCreateContent",
|
||||
"group": "Getting Started",
|
||||
"groupOrder": 100,
|
||||
"requiredSections": [
|
||||
"content",
|
||||
"media",
|
||||
"settings",
|
||||
"developer",
|
||||
"users",
|
||||
"member",
|
||||
"forms"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"title": "Creating your first content node",
|
||||
@@ -253,6 +279,15 @@
|
||||
"alias": "umbIntroRenderInTemplate",
|
||||
"group": "Getting Started",
|
||||
"groupOrder": 100,
|
||||
"requiredSections": [
|
||||
"content",
|
||||
"media",
|
||||
"settings",
|
||||
"developer",
|
||||
"users",
|
||||
"member",
|
||||
"forms"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"title": "Render your content in a template",
|
||||
@@ -299,6 +334,15 @@
|
||||
"alias": "umbIntroViewHomePage",
|
||||
"group": "Getting Started",
|
||||
"groupOrder": 100,
|
||||
"requiredSections": [
|
||||
"content",
|
||||
"media",
|
||||
"settings",
|
||||
"developer",
|
||||
"users",
|
||||
"member",
|
||||
"forms"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"title": "View your Umbraco site",
|
||||
@@ -339,6 +383,15 @@
|
||||
"alias": "umbIntroMediaSection",
|
||||
"group": "Getting Started",
|
||||
"groupOrder": 100,
|
||||
"requiredSections": [
|
||||
"content",
|
||||
"media",
|
||||
"settings",
|
||||
"developer",
|
||||
"users",
|
||||
"member",
|
||||
"forms"
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"title": "How to use the media library",
|
||||
@@ -368,7 +421,8 @@
|
||||
{
|
||||
"element": "[data-element='editor-media'] [data-element='editor-name-field']",
|
||||
"title": "Enter a name",
|
||||
"content": "<p>Enter <code>My Images</code> in the field.</p>"
|
||||
"content": "<p>Enter <code>My Images</code> in the field.</p>",
|
||||
"view": "foldername"
|
||||
},
|
||||
{
|
||||
"element": "[data-element='editor-media'] [data-element='button-save']",
|
||||
@@ -391,6 +445,7 @@
|
||||
},
|
||||
{
|
||||
"element": "[data-element='editor-media'] [data-element='property-umbracoFile']",
|
||||
"elementPreventClick": true,
|
||||
"title": "The uploaded image",
|
||||
"content": "<p>Here you can see the image you have uploaded.</p>"
|
||||
},
|
||||
@@ -417,6 +472,7 @@
|
||||
},
|
||||
{
|
||||
"element": "[data-element='editor-container']",
|
||||
"elementPreventClick": true,
|
||||
"title": "Using media items",
|
||||
"content": "You can reference a media item directly in a template by using the path or try adding a Media Picker to a document type property so you can select media items from the content section."
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|al
|
||||
thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],
|
||||
-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],
|
||||
-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],
|
||||
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
|
||||
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],
|
||||
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
|
||||
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
|
||||
</validElements>
|
||||
|
||||
@@ -248,7 +248,7 @@ img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|al
|
||||
thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],
|
||||
-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],
|
||||
-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],
|
||||
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],
|
||||
-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],
|
||||
dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],
|
||||
param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]]]>
|
||||
</validElements>
|
||||
@@ -271,4 +271,4 @@ param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|cla
|
||||
}
|
||||
</config>
|
||||
</customConfig>
|
||||
</tinymceConfig>
|
||||
</tinymceConfig>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.9.4" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
|
||||
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
|
||||
<package id="dotless" version="1.5.2" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.89" targetFramework="net45" />
|
||||
@@ -36,5 +36,5 @@
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
|
||||
<package id="System.Reflection.Metadata" version="1.0.21" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.8" targetFramework="net45" />
|
||||
<package id="Umbraco.ModelsBuilder" version="3.0.10" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -43,6 +43,7 @@
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="pinterest" content="nopin" />
|
||||
|
||||
<title ng-bind="$root.locationTitle">Umbraco</title>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/simple.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="macroTasks" />
|
||||
<delete assembly="umbraco" type="macroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/simple.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="macroTasks" />
|
||||
<delete assembly="umbraco" type="macroTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
<key alias="documentTypeWithoutTemplate">Dokumenttype uden skabelon</key>
|
||||
<key alias="newFolder">Ny mappe</key>
|
||||
<key alias="newDataType">Ny datatype</key>
|
||||
<key alias="newJavascriptFile">Ny javascript fil</key>
|
||||
<key alias="newJavascriptFile">Ny JavaScript-fil</key>
|
||||
<key alias="newEmptyPartialView">Ny tom partial view</key>
|
||||
<key alias="newFolder">Ny mappe</key>
|
||||
<key alias="newPartialViewMacro">Ny partial view makro</key>
|
||||
@@ -1219,6 +1219,12 @@ Mange hilsner fra Umbraco robotten
|
||||
</area>
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Vælg indholdstype</key>
|
||||
<key alias="chooseLayout">Vælg layout</key>
|
||||
<key alias="addRows">Tilføj række</key>
|
||||
|
||||
@@ -850,6 +850,12 @@ Wenn Sie sich für Runway entscheiden, können Sie optional Blöcke nutzen, die
|
||||
<key alias="template">Vorlage</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Element hinzufügen</key>
|
||||
<key alias="addRows">Zeilenlayout auswählen</key>
|
||||
<key alias="addElement">Element mit <i class="icon icon-add blue"></i> hinzufügen</key>
|
||||
|
||||
@@ -1506,6 +1506,12 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
</area>
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
@@ -1954,7 +1960,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
</body>
|
||||
</html>]]>
|
||||
</key>
|
||||
|
||||
<key alias="invite">Invite</key>
|
||||
</area>
|
||||
|
||||
<area alias="validation">
|
||||
|
||||
@@ -1512,6 +1512,12 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="template">Template</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
@@ -1958,6 +1964,7 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
</body>
|
||||
</html>]]>
|
||||
</key>
|
||||
<key alias="invite">Invite</key>
|
||||
</area>
|
||||
<area alias="validation">
|
||||
<key alias="validation">Validation</key>
|
||||
|
||||
@@ -754,6 +754,12 @@
|
||||
<key alias="template">Plantilla</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Insertar control</key>
|
||||
<key alias="chooseLayout">Choose layout</key>
|
||||
<key alias="addRows">Añade más filas</key>
|
||||
|
||||
@@ -1201,6 +1201,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
|
||||
</area>
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choisissez le type de contenu</key>
|
||||
<key alias="chooseLayout">Choisissez une mise en page</key>
|
||||
<key alias="addRows">Ajouter une ligne</key>
|
||||
|
||||
@@ -745,6 +745,12 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="template">תבנית</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
|
||||
@@ -732,6 +732,12 @@ Per gestire il tuo sito web, è sufficiente aprire il back office di Umbraco e i
|
||||
<key alias="template">Template</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
|
||||
@@ -976,6 +976,12 @@ Runwayをインストールして作られた新しいウェブサイトがど
|
||||
</area>
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">挿入するアイテムを選択する</key>
|
||||
<key alias="addLayout">レイアウトを選択</key>
|
||||
<key alias="addRows">行の追加</key>
|
||||
|
||||
@@ -727,6 +727,12 @@
|
||||
<key alias="template">템플릿</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
|
||||
@@ -1039,6 +1039,12 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
<key alias="template">Sjabloon</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Item toevoegen</key>
|
||||
<key alias="chooseLayout">Kies de indeling</key>
|
||||
<key alias="addRows">Kies een indeling voor deze pagina om content toe te kunnen voegen</key>
|
||||
|
||||
@@ -1274,6 +1274,12 @@ Naciśnij przycisk <strong>instaluj</strong>, aby zainstalować bazę danych Umb
|
||||
</area>
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Wybierz typ treści</key>
|
||||
<key alias="chooseLayout">Wybierz układ</key>
|
||||
<key alias="addRows">Dodaj wiersz</key>
|
||||
|
||||
@@ -715,6 +715,12 @@ Você pode publicar esta página e todas suas sub-páginas ao selecionar <em>pub
|
||||
<key alias="template">Modelo</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Choose type of content</key>
|
||||
<key alias="chooseLayout">Choose a layout</key>
|
||||
<key alias="addRows">Add a row</key>
|
||||
|
||||
@@ -667,6 +667,12 @@
|
||||
<key alias="text">Текст</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="addElement">Добавить содержимое</key>
|
||||
<key alias="dropElement">Сбросить содержимое</key>
|
||||
<key alias="addGridLayout">Добавить шаблон сетки</key>
|
||||
|
||||
@@ -780,6 +780,12 @@
|
||||
<key alias="template">Sidmall</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Lägg till</key>
|
||||
<key alias="chooseLayout">Choose layout</key>
|
||||
<key alias="addRows">Lägg till rad</key>
|
||||
|
||||
@@ -930,6 +930,12 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="template">Template</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">Insert control</key>
|
||||
<key alias="addRows">Choose a layout for the page</key>
|
||||
<key alias="addElement"><![CDATA[To start, click the <i class="icon icon-add blue"></i> below and add your first element]]></key>
|
||||
|
||||
@@ -1230,6 +1230,12 @@
|
||||
</area>
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="rte">Rich Text Editor</key>
|
||||
<key alias="media">Image</key>
|
||||
<key alias="macro">Macro</key>
|
||||
<key alias="embed">Embed</key>
|
||||
<key alias="headline">Headline</key>
|
||||
<key alias="quote">Quote</key>
|
||||
<key alias="insertControl">选择内容类别</key>
|
||||
<key alias="chooseLayout">选择一项布局</key>
|
||||
<key alias="addRows">添加一行</key>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
@@ -83,36 +83,28 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
public override void Refresh(string jsonPayload)
|
||||
{
|
||||
ClearCache(DeserializeFromJsonPayload(jsonPayload));
|
||||
ClearCache();
|
||||
base.Refresh(jsonPayload);
|
||||
}
|
||||
|
||||
public override void Refresh(int id)
|
||||
{
|
||||
ClearCache(FromMemberGroup(ApplicationContext.Current.Services.MemberGroupService.GetById(id)));
|
||||
ClearCache();
|
||||
base.Refresh(id);
|
||||
}
|
||||
|
||||
public override void Remove(int id)
|
||||
{
|
||||
ClearCache(FromMemberGroup(ApplicationContext.Current.Services.MemberGroupService.GetById(id)));
|
||||
ClearCache();
|
||||
base.Remove(id);
|
||||
}
|
||||
|
||||
private void ClearCache(params JsonPayload[] payloads)
|
||||
private void ClearCache()
|
||||
{
|
||||
if (payloads == null) return;
|
||||
|
||||
var memberGroupCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IMemberGroup>();
|
||||
payloads.ForEach(payload =>
|
||||
{
|
||||
if (payload != null && memberGroupCache)
|
||||
{
|
||||
memberGroupCache.Result.ClearCacheByKeySearch(string.Format("{0}.{1}", typeof(IMemberGroup).FullName, payload.Name));
|
||||
memberGroupCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey<IMemberGroup>(payload.Id));
|
||||
}
|
||||
});
|
||||
|
||||
// Since we cache by group name, it could be problematic when renaming to
|
||||
// previously existing names - see http://issues.umbraco.org/issue/U4-10846.
|
||||
// To work around this, just clear all the cache items
|
||||
ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.ClearCache<IMemberGroup>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Security;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
@@ -21,6 +17,13 @@ namespace Umbraco.Web.Controllers
|
||||
return CurrentUmbracoPage();
|
||||
}
|
||||
|
||||
// U4-10762 Server error with "Register Member" snippet (Cannot save member with empty name)
|
||||
// If name field is empty, add the email address instead
|
||||
if (string.IsNullOrEmpty(model.Name) && string.IsNullOrEmpty(model.Email) == false)
|
||||
{
|
||||
model.Name = model.Email;
|
||||
}
|
||||
|
||||
MembershipCreateStatus status;
|
||||
var member = Members.RegisterMember(model, out status, model.LoginOnSuccess);
|
||||
|
||||
@@ -36,7 +39,6 @@ namespace Umbraco.Web.Controllers
|
||||
return Redirect(model.RedirectUrl);
|
||||
}
|
||||
//redirect to current page by default
|
||||
|
||||
return RedirectToCurrentUmbracoPage();
|
||||
case MembershipCreateStatus.InvalidUserName:
|
||||
ModelState.AddModelError((model.UsernameIsEmail || model.Username == null)
|
||||
|
||||
@@ -7,13 +7,10 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoApplicationAuthorize(Constants.Applications.Content)]
|
||||
public class TourController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
public IEnumerable<BackOfficeTourFile> GetTours()
|
||||
@@ -24,7 +21,7 @@ namespace Umbraco.Web.Editors
|
||||
return result;
|
||||
|
||||
var filters = TourFilterResolver.Current.Filters.ToList();
|
||||
|
||||
|
||||
//get all filters that will be applied to all tour aliases
|
||||
var aliasOnlyFilters = filters.Where(x => x.PluginName == null && x.TourFileName == null).ToList();
|
||||
|
||||
@@ -65,8 +62,28 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
}
|
||||
//Get all allowed sections for the current user
|
||||
var allowedSections = UmbracoContext.Current.Security.CurrentUser.AllowedSections.ToList();
|
||||
|
||||
return result.OrderBy(x => x.FileName, StringComparer.InvariantCultureIgnoreCase);
|
||||
var toursToBeRemoved = new List<BackOfficeTourFile>();
|
||||
|
||||
//Checking to see if the user has access to the required tour sections, else we remove the tour
|
||||
foreach (var backOfficeTourFile in result)
|
||||
{
|
||||
foreach (var tour in backOfficeTourFile.Tours)
|
||||
{
|
||||
foreach (var toursRequiredSection in tour.RequiredSections)
|
||||
{
|
||||
if (allowedSections.Contains(toursRequiredSection) == false)
|
||||
{
|
||||
toursToBeRemoved.Add(backOfficeTourFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.Except(toursToBeRemoved).OrderBy(x => x.FileName, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
private void TryParseTourFile(string tourFile,
|
||||
@@ -80,7 +97,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
//get the filters specific to this file
|
||||
var fileFilters = filters.Where(x => x.TourFileName != null && x.TourFileName.IsMatch(fileName)).ToList();
|
||||
|
||||
|
||||
//If there is any filter applied to match the file only (no tour alias) then ignore the file entirely
|
||||
var isFileFiltered = fileFilters.Any(x => x.TourAlias == null);
|
||||
if (isFileFiltered) return;
|
||||
@@ -118,4 +135,4 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,18 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
IEnumerable<IPublishedContent> TypedSearch(string term, bool useWildCards = true, string searchProvider = null);
|
||||
|
||||
/// <summary>
|
||||
/// Searches content
|
||||
/// </summary>
|
||||
/// <param name="skip"></param>
|
||||
/// <param name="take"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="term"></param>
|
||||
/// <param name="useWildCards"></param>
|
||||
/// <param name="searchProvider"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IPublishedContent> TypedSearch(int skip, int take, out int totalRecords, string term, bool useWildCards = true, string searchProvider = null);
|
||||
|
||||
/// <summary>
|
||||
/// Searhes content
|
||||
/// </summary>
|
||||
@@ -57,5 +69,16 @@ namespace Umbraco.Web
|
||||
/// <param name="searchProvider"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IPublishedContent> TypedSearch(Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null);
|
||||
|
||||
/// <summary>
|
||||
/// Searhes content
|
||||
/// </summary>
|
||||
/// <param name="totalrecords"></param>
|
||||
/// <param name="criteria"></param>
|
||||
/// <param name="searchProvider"></param>
|
||||
/// <param name="skip"></param>
|
||||
/// <param name="take"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IPublishedContent> TypedSearch(int skip, int take, out int totalrecords, Examine.SearchCriteria.ISearchCriteria criteria, Examine.Providers.BaseSearchProvider searchProvider = null);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
@@ -18,6 +19,8 @@ namespace Umbraco.Web.Models
|
||||
public int GroupOrder { get; set; }
|
||||
[DataMember(Name = "allowDisable")]
|
||||
public bool AllowDisable { get; set; }
|
||||
[DataMember(Name = "requiredSections")]
|
||||
public List<string> RequiredSections { get; set; }
|
||||
[DataMember(Name = "steps")]
|
||||
public BackOfficeTourStep[] Steps { get; set; }
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
if (source.DefaultTemplate != null)
|
||||
dest.SetDefaultTemplate(applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate));
|
||||
else
|
||||
dest.SetDefaultTemplate(null);
|
||||
|
||||
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
|
||||
});
|
||||
|
||||
@@ -204,10 +204,24 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
var allContentPermissions = applicationContext.Services.UserService.GetPermissions(@group, true)
|
||||
.ToDictionary(x => x.EntityId, x => x);
|
||||
|
||||
var contentEntities = allContentPermissions.Keys.Count == 0
|
||||
? new IUmbracoEntity[0]
|
||||
: applicationContext.Services.EntityService.GetAll(UmbracoObjectTypes.Document, allContentPermissions.Keys.ToArray());
|
||||
|
||||
IEnumerable<IUmbracoEntity> contentEntities;
|
||||
if (allContentPermissions.Keys.Count == 0)
|
||||
{
|
||||
contentEntities = new IUmbracoEntity[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// a group can end up with way more than 2000 assigned permissions,
|
||||
// so we need to break them into groups in order to avoid breaking
|
||||
// the entity service due to too many Sql parameters.
|
||||
|
||||
var list = new List<IUmbracoEntity>();
|
||||
contentEntities = list;
|
||||
var entityService = applicationContext.Services.EntityService;
|
||||
foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(2000))
|
||||
list.AddRange(entityService.GetAll(UmbracoObjectTypes.Document, idGroup.ToArray()));
|
||||
}
|
||||
|
||||
var allAssignedPermissions = new List<AssignedContentPermissions>();
|
||||
foreach (var entity in contentEntities)
|
||||
@@ -376,8 +390,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerable<EntityBasic> GetStartNodeValues(int[] startNodeIds,
|
||||
ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType,
|
||||
private IEnumerable<EntityBasic> GetStartNodeValues(int[] startNodeIds,
|
||||
ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType,
|
||||
string localizedKey)
|
||||
{
|
||||
if (startNodeIds.Length > 0)
|
||||
@@ -392,7 +406,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
return startNodes;
|
||||
}
|
||||
return Enumerable.Empty<EntityBasic>();
|
||||
}
|
||||
}
|
||||
|
||||
private void MapUserGroupBasic(ServiceContext services, dynamic group, UserGroupBasic display)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Umbraco.Web.Models.Trees
|
||||
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
|
||||
internal MenuItem Add(IAction action, string name)
|
||||
{
|
||||
var item = new MenuItem(action);
|
||||
var item = new MenuItem(action, name);
|
||||
|
||||
DetectLegacyActionMenu(action.GetType(), item);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@@ -13,8 +12,10 @@ namespace Umbraco.Web.Mvc
|
||||
/// <summary>
|
||||
/// Allows for Model Binding any IPublishedContent or IRenderModel
|
||||
/// </summary>
|
||||
public class RenderModelBinder : DefaultModelBinder, IModelBinder, IModelBinderProvider
|
||||
public class RenderModelBinder : DefaultModelBinder, IModelBinderProvider
|
||||
{
|
||||
public static RenderModelBinder Instance = new RenderModelBinder();
|
||||
|
||||
/// <summary>
|
||||
/// Binds the model to a value by using the specified controller context and binding context.
|
||||
/// </summary>
|
||||
@@ -132,10 +133,30 @@ namespace Umbraco.Web.Mvc
|
||||
return null;
|
||||
}
|
||||
|
||||
public class ModelBindingArgs : EventArgs
|
||||
{
|
||||
public ModelBindingArgs(Type sourceType, Type modelType, StringBuilder message)
|
||||
{
|
||||
SourceType = sourceType;
|
||||
ModelType = modelType;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public bool SourceIsContent;
|
||||
public bool ViewModelIsContent;
|
||||
public Type SourceType { get; set; }
|
||||
public Type ModelType { get; set; }
|
||||
public StringBuilder Message { get; private set; }
|
||||
public bool Restart { get; set; }
|
||||
}
|
||||
|
||||
public static event EventHandler<ModelBindingArgs> ModelBindingException;
|
||||
|
||||
private static void ThrowModelBindingException(bool sourceContent, bool modelContent, Type sourceType, Type modelType)
|
||||
{
|
||||
var msg = new StringBuilder();
|
||||
|
||||
// prepare message
|
||||
msg.Append("Cannot bind source");
|
||||
if (sourceContent) msg.Append(" content");
|
||||
msg.Append(" type ");
|
||||
@@ -146,28 +167,24 @@ namespace Umbraco.Web.Mvc
|
||||
msg.Append(modelType.FullName);
|
||||
msg.Append(".");
|
||||
|
||||
// compare FullName for the time being because when upgrading ModelsBuilder,
|
||||
// Umbraco does not know about the new attribute type - later on, can compare
|
||||
// on type directly (ie after v7.4.2).
|
||||
var sourceAttr = sourceType.Assembly.CustomAttributes.FirstOrDefault(x =>
|
||||
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
|
||||
var modelAttr = modelType.Assembly.CustomAttributes.FirstOrDefault(x =>
|
||||
x.AttributeType.FullName == "Umbraco.ModelsBuilder.PureLiveAssemblyAttribute");
|
||||
// raise event, to give model factories a chance at reporting
|
||||
// the error with more details, and optionally request that
|
||||
// the application restarts.
|
||||
|
||||
// bah.. names are App_Web_all.generated.cs.8f9494c4.jjuvxz55 so they ARE different, fuck!
|
||||
// we cannot compare purely on type.FullName 'cos we might be trying to map Sub to Main = fails!
|
||||
if (sourceAttr != null && modelAttr != null
|
||||
&& sourceType.Assembly.GetName().Version.Revision != modelType.Assembly.GetName().Version.Revision)
|
||||
var args = new ModelBindingArgs(sourceType, modelType, msg);
|
||||
if (ModelBindingException != null)
|
||||
ModelBindingException(Instance, args);
|
||||
|
||||
if (args.Restart)
|
||||
{
|
||||
msg.Append(" Types come from two PureLive assemblies with different versions,");
|
||||
msg.Append(" this usually indicates that the application is in an unstable state.");
|
||||
msg.Append(" The application is restarting now, reload the page and it should work.");
|
||||
var context = HttpContext.Current;
|
||||
if (context == null)
|
||||
AppDomain.Unload(AppDomain.CurrentDomain);
|
||||
else
|
||||
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
|
||||
}
|
||||
msg.Append(" The application is restarting now.");
|
||||
|
||||
var context = HttpContext.Current;
|
||||
if (context == null)
|
||||
AppDomain.Unload(AppDomain.CurrentDomain);
|
||||
else
|
||||
ApplicationContext.Current.RestartApplicationPool(new HttpContextWrapper(context));
|
||||
}
|
||||
|
||||
throw new ModelBindingException(msg.ToString());
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ using System.Security;
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Umbraco.Headless")]
|
||||
|
||||
//allow custom unit-testing code to access internals through custom adapters
|
||||
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")] // backwards compat.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user