Merge remote-tracking branch 'origin/7.1.4' into 7.1.3-variations
This commit is contained in:
+10
-1
@@ -1,5 +1,9 @@
|
||||
@ECHO OFF
|
||||
SET release=7.1.2
|
||||
IF NOT EXIST UmbracoVersion.txt (
|
||||
ECHO UmbracoVersion.txt missing!
|
||||
GOTO :showerror
|
||||
)
|
||||
SET /p release=<UmbracoVersion.txt
|
||||
SET comment=
|
||||
SET version=%release%
|
||||
|
||||
@@ -15,6 +19,11 @@ SET nuGetFolder=%CD%\..\src\packages\
|
||||
ECHO Removing the belle build folder to make sure everything is clean as a whistle
|
||||
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
|
||||
|
||||
ECHO Removing existing built files to make sure everything is clean as a whistle
|
||||
DEL /F /Q UmbracoCms.*.zip
|
||||
DEL /F /Q UmbracoCms.*.nupkg
|
||||
DEL /F /Q webpihash.txt
|
||||
|
||||
ECHO Performing MSBuild and producing Umbraco binaries zip files
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
|
||||
|
||||
+1
-1
@@ -325,7 +325,7 @@
|
||||
Regex="CurrentComment { get { return "([a-zA-Z]+)?""
|
||||
ReplacementText="CurrentComment { get { return "$(BUILD_COMMENT)""/>
|
||||
|
||||
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.targets"
|
||||
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.props"
|
||||
Namespaces="<Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' />"
|
||||
Query="//x:UmbracoVersion"
|
||||
Value="$(NewVersion)" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@ECHO OFF
|
||||
SET release=%1
|
||||
ECHO Installing Npm NuGet Package
|
||||
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
@@ -26,7 +27,7 @@ ECHO Do npm install and the grunt build of Belle
|
||||
call npm install
|
||||
call npm install -g grunt-cli
|
||||
call npm install -g bower
|
||||
call grunt build --buildversion=7.1.2
|
||||
call grunt build --buildversion=%release%
|
||||
|
||||
ECHO Reset path to what it was before
|
||||
path=%oldPath%
|
||||
|
||||
@@ -67,5 +67,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\bin\umbraco.XmlSerializers.dll" target="lib\umbraco.XmlSerializers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UmbracoExamine.dll" target="lib\UmbracoExamine.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\UrlRewritingNet.UrlRewriter.dll" target="lib\UrlRewritingNet.UrlRewriter.dll" />
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForPackageDependsOn>
|
||||
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
AddUmbracoFilesToOutput;
|
||||
$(CopyAllFilesToSingleFolderForPackageDependsOn);
|
||||
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<UmbracoVersion>7.1.2</UmbracoVersion>
|
||||
</PropertyGroup>
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<PropertyGroup>
|
||||
<UmbracoFilesFolder>..\packages\UmbracoCms.$(UmbracoVersion)\UmbracoFiles\</UmbracoFilesFolder>
|
||||
<UmbracoFilesFolder>$(MSBuildThisFileDirectory)..\UmbracoFiles\</UmbracoFilesFolder>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include="$(UmbracoFilesFolder)**\*" />
|
||||
@@ -33,6 +30,9 @@
|
||||
<CustomFilesToInclude Include=".\Config\Splashes\**\*">
|
||||
<Dir>Config\Splashes</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\data\**\*">
|
||||
<Dir>data</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco\**\*">
|
||||
<Dir>umbraco</Dir>
|
||||
</CustomFilesToInclude>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
param($rootPath, $toolsPath, $package, $project)
|
||||
|
||||
if ($project) {
|
||||
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
|
||||
$backupPath = Join-Path (Split-Path $project.FullName -Parent) "\App_Data\NuGetBackup\$dateTime"
|
||||
$copyLogsPath = Join-Path $backupPath "CopyLogs"
|
||||
$projectDestinationPath = Split-Path $project.FullName -Parent
|
||||
|
||||
# Create backup folder and logs folder if it doesn't exist yet
|
||||
New-Item -ItemType Directory -Force -Path $backupPath
|
||||
New-Item -ItemType Directory -Force -Path $copyLogsPath
|
||||
|
||||
# After backing up, remove all dlls from bin folder in case dll files are included in the VS project
|
||||
# See: http://issues.umbraco.org/issue/U4-4930
|
||||
$umbracoBinFolder = Join-Path $projectDestinationPath "bin"
|
||||
if(Test-Path $umbracoBinFolder) {
|
||||
$umbracoBinBackupPath = Join-Path $backupPath "bin"
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBinBackupPath
|
||||
|
||||
robocopy $umbracoBinFolder $umbracoBinBackupPath /e /LOG:$copyLogsPath\UmbracoBinBackup.log
|
||||
Remove-Item $umbracoBinFolder\*.dll -Force -Confirm:$false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
7.1.3
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.1.2");
|
||||
private static readonly Version Version = new Version("7.1.3");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -133,29 +133,6 @@ namespace Umbraco.Core.Models
|
||||
Key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being updated
|
||||
/// </summary>
|
||||
/// <remarks>Modified Date is set and a new Version guid is set</remarks>
|
||||
internal override void UpdatingEntity()
|
||||
{
|
||||
base.UpdatingEntity();
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentType)base.DeepClone();
|
||||
var propertyGroups = PropertyGroups.Select(x => (PropertyGroup)x.DeepClone()).ToList();
|
||||
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
|
||||
//set the property types that are not part of a group
|
||||
clone.PropertyTypes = PropertyTypeCollection
|
||||
.Where(x => x.PropertyGroupId == null)
|
||||
.Select(x => (PropertyType)x.DeepClone()).ToList();
|
||||
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
|
||||
|
||||
@@ -331,11 +331,6 @@ namespace Umbraco.Core.Models
|
||||
get { return _additionalData; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
public IDictionary<string, object> AdditionalData { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of integer Ids for allowed ContentTypes
|
||||
/// </summary>
|
||||
@@ -356,7 +351,9 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// List of PropertyGroups available on this ContentType
|
||||
/// </summary>
|
||||
/// <remarks>A PropertyGroup corresponds to a Tab in the UI</remarks>
|
||||
/// <remarks>
|
||||
/// A PropertyGroup corresponds to a Tab in the UI
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public virtual PropertyGroupCollection PropertyGroups
|
||||
{
|
||||
@@ -372,7 +369,13 @@ namespace Umbraco.Core.Models
|
||||
/// List of PropertyTypes available on this ContentType.
|
||||
/// This list aggregates PropertyTypes across the PropertyGroups.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Marked as DoNotClone because the result of this property is not the natural result of the data, it is
|
||||
/// a union of data so when auto-cloning if the setter is used it will be setting the unnatural result of the
|
||||
/// data. We manually clone this instead.
|
||||
/// </remarks>
|
||||
[IgnoreDataMember]
|
||||
[DoNotClone]
|
||||
public virtual IEnumerable<PropertyType> PropertyTypes
|
||||
{
|
||||
get
|
||||
@@ -388,6 +391,14 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the property type collection containing types that are non-groups - used for tests
|
||||
/// </summary>
|
||||
internal IEnumerable<PropertyType> NonGroupedPropertyTypes
|
||||
{
|
||||
get { return _propertyTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A boolean flag indicating if a property type has been removed from this instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -584,5 +595,19 @@ namespace Umbraco.Core.Models
|
||||
propertyType.ResetDirtyProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentTypeBase)base.DeepClone();
|
||||
|
||||
//need to manually wire up the event handlers for the property type collections - we've ensured
|
||||
// its ignored from the auto-clone process because its return values are unions, not raw and
|
||||
// we end up with duplicates, see: http://issues.umbraco.org/issue/U4-4842
|
||||
|
||||
clone._propertyTypes = (PropertyTypeCollection)_propertyTypes.DeepClone();
|
||||
clone._propertyTypes.CollectionChanged += clone.PropertyTypesChanged;
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,29 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to attribute properties that have a setter and are a reference type
|
||||
/// that should be ignored for cloning when using the DeepCloneHelper
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// This attribute must be used:
|
||||
/// * when the property is backed by a field but the result of the property is the un-natural data stored in the field
|
||||
///
|
||||
/// This attribute should not be used:
|
||||
/// * when the property is virtual
|
||||
/// * when the setter performs additional required logic other than just setting the underlying field
|
||||
///
|
||||
/// </remarks>
|
||||
internal class DoNotCloneAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class DeepCloneHelper
|
||||
{
|
||||
/// <summary>
|
||||
@@ -25,8 +45,10 @@ namespace Umbraco.Core.Models
|
||||
|
||||
var refProperties = inputType.GetProperties()
|
||||
.Where(x =>
|
||||
//is not attributed with the ignore clone attribute
|
||||
x.GetCustomAttribute<DoNotCloneAttribute>() == null
|
||||
//reference type but not string
|
||||
x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|
||||
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|
||||
//settable
|
||||
&& x.CanWrite
|
||||
//non-indexed
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Defines a Property for a Macro
|
||||
/// </summary>
|
||||
public interface IMacroProperty : IValueObject, IDeepCloneable
|
||||
public interface IMacroProperty : IValueObject, IDeepCloneable, IRememberBeingDirty
|
||||
{
|
||||
[DataMember]
|
||||
int Id { get; set; }
|
||||
|
||||
@@ -24,6 +24,44 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to update an existing macro property
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="sortOrder"></param>
|
||||
/// <param name="editorAlias"></param>
|
||||
/// <param name="currentAlias">
|
||||
/// The existing property alias
|
||||
/// </param>
|
||||
/// <param name="newAlias"></param>
|
||||
public void UpdateProperty(string currentAlias, string name = null, int? sortOrder = null, string editorAlias = null, string newAlias = null)
|
||||
{
|
||||
var prop = this[currentAlias];
|
||||
if (prop == null)
|
||||
{
|
||||
throw new InvalidOperationException("No property exists with alias " + currentAlias);
|
||||
}
|
||||
|
||||
if (name.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
prop.Name = name;
|
||||
}
|
||||
if (sortOrder.HasValue)
|
||||
{
|
||||
prop.SortOrder = sortOrder.Value;
|
||||
}
|
||||
if (name.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
prop.EditorAlias = editorAlias;
|
||||
}
|
||||
|
||||
if (newAlias.IsNullOrWhiteSpace() == false && currentAlias != newAlias)
|
||||
{
|
||||
prop.Alias = newAlias;
|
||||
ChangeKey(currentAlias, newAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Represents a stored pre-value field value
|
||||
/// </summary>
|
||||
public class PreValue
|
||||
public class PreValue : IDeepCloneable
|
||||
{
|
||||
public PreValue(int id, string value, int sortOrder)
|
||||
{
|
||||
@@ -37,5 +37,12 @@
|
||||
/// The sort order stored for the pre-value field value
|
||||
/// </summary>
|
||||
public int SortOrder { get; private set; }
|
||||
|
||||
public virtual object DeepClone()
|
||||
{
|
||||
//Memberwise clone on PreValue will work since it doesn't have any deep elements
|
||||
var clone = (PreValue)MemberwiseClone();
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Models
|
||||
/// Most legacy property editors won't support the dictionary format but new property editors should always use the dictionary format.
|
||||
/// In order to get overrideable pre-values working we need a dictionary since we'll have to reference a pre-value by a key.
|
||||
/// </remarks>
|
||||
public class PreValueCollection
|
||||
public class PreValueCollection : IDeepCloneable
|
||||
{
|
||||
private IDictionary<string, PreValue> _preValuesAsDictionary;
|
||||
private IEnumerable<PreValue> _preValuesAsArray;
|
||||
@@ -82,5 +82,21 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public object DeepClone()
|
||||
{
|
||||
var clone = (PreValueCollection) MemberwiseClone();
|
||||
if (_preValuesAsArray != null)
|
||||
{
|
||||
clone._preValuesAsArray = _preValuesAsArray.Select(x => (PreValue)x.DeepClone()).ToArray();
|
||||
}
|
||||
if (_preValuesAsDictionary != null)
|
||||
{
|
||||
clone._preValuesAsDictionary = _preValuesAsDictionary.ToDictionary(x => x.Key, x => (PreValue)x.Value.DeepClone());
|
||||
}
|
||||
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,11 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
InitializeIndexes();
|
||||
}
|
||||
|
||||
// create detached content type - ie does not match anything in the DB
|
||||
internal PublishedContentType(string alias, IEnumerable<PublishedPropertyType> propertyTypes)
|
||||
: this (0, alias, propertyTypes)
|
||||
{ }
|
||||
|
||||
private void InitializeIndexes()
|
||||
{
|
||||
for (var i = 0; i < _propertyTypes.Length; i++)
|
||||
|
||||
@@ -135,6 +135,28 @@ namespace Umbraco.Core
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows us to change the key of an item
|
||||
/// </summary>
|
||||
/// <param name="currentKey"></param>
|
||||
/// <param name="newKey"></param>
|
||||
public virtual void ChangeKey(TKey currentKey, TKey newKey)
|
||||
{
|
||||
if (!Indecies.ContainsKey(currentKey))
|
||||
{
|
||||
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
|
||||
}
|
||||
if (ContainsKey(newKey))
|
||||
{
|
||||
throw new DuplicateKeyException(newKey.ToString());
|
||||
}
|
||||
|
||||
var currentIndex = Indecies[currentKey];
|
||||
|
||||
Indecies.Remove(currentKey);
|
||||
Indecies.Add(newKey, currentIndex);
|
||||
}
|
||||
|
||||
internal class DuplicateKeyException : Exception
|
||||
{
|
||||
|
||||
|
||||
@@ -128,9 +128,9 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
public void Save(Type type, IEntity entity)
|
||||
{
|
||||
//IMPORTANT: we must clone to store, see: http://issues.umbraco.org/issue/U4-4259
|
||||
entity = (IEntity)entity.DeepClone();
|
||||
var clone = (IEntity)entity.DeepClone();
|
||||
|
||||
var key = GetCompositeId(type, entity.Id);
|
||||
var key = GetCompositeId(type, clone.Id);
|
||||
|
||||
_keyTracker.TryAdd(key);
|
||||
|
||||
@@ -139,11 +139,11 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.Set(key, entity, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
_memoryCache.Set(key, clone, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(5) });
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRuntime.Cache.Insert(key, entity, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
|
||||
HttpRuntime.Cache.Insert(key, clone, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -295,8 +295,8 @@ AND umbracoNode.id <> @id",
|
||||
var cached = _cacheHelper.RuntimeCache.GetCacheItemsByKeySearch<PreValueCollection>(GetPrefixedCacheKey(dataTypeId));
|
||||
if (cached != null && cached.Any())
|
||||
{
|
||||
//return from the cache
|
||||
return cached.First();
|
||||
//return from the cache, ensure it's a cloned result
|
||||
return (PreValueCollection)cached.First().DeepClone();
|
||||
}
|
||||
|
||||
l.UpgradeToWriteLock();
|
||||
|
||||
@@ -493,14 +493,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// Is this the same UmbracoEntity as the current one we're processing
|
||||
if (Current != null && Current.Key == a.uniqueID)
|
||||
{
|
||||
// Add this UmbracoProperty to the current additional data
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
// Add this UmbracoProperty to the current additional data
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
|
||||
// Return null to indicate we're not done with this UmbracoEntity yet
|
||||
return null;
|
||||
@@ -516,14 +519,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Current = _factory.BuildEntityFromDynamic(a);
|
||||
|
||||
//add the property/create the prop list if null
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
if (p != null && p.PropertyAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
//add the property/create the prop list if null
|
||||
Current.AdditionalData[p.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = p.PropertyEditorAlias,
|
||||
Value = p.NTextValue.IsNullOrWhiteSpace()
|
||||
? p.NVarcharValue
|
||||
: p.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
|
||||
// Return the now populated previous UmbracoEntity (or null if first time through)
|
||||
return prev;
|
||||
|
||||
@@ -165,9 +165,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
Database.Update(dto);
|
||||
|
||||
//update the sections if they've changed
|
||||
//update the properties if they've changed
|
||||
var macro = (Macro)entity;
|
||||
if (macro.IsPropertyDirty("Properties"))
|
||||
if (macro.IsPropertyDirty("Properties") || macro.Properties.Any(x => x.IsDirty()))
|
||||
{
|
||||
//now we need to delete any props that have been removed
|
||||
foreach (var propAlias in macro.RemovedProperties)
|
||||
@@ -188,7 +188,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.Update(propDto);
|
||||
//only update if it's dirty
|
||||
if (macro.Properties[propDto.Alias].IsDirty())
|
||||
{
|
||||
Database.Update(propDto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace Umbraco.Core
|
||||
//this is from SqlMetal and just makes it a bit of fun to allow pluralisation
|
||||
public static string MakePluralName(this string name)
|
||||
{
|
||||
if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("ss", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase)))
|
||||
if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("s", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
name = name + "es";
|
||||
return name;
|
||||
|
||||
@@ -152,6 +152,7 @@ namespace Umbraco.Tests.Models
|
||||
}
|
||||
Assert.AreNotSame(clone.PropertyTypes, contentType.PropertyTypes);
|
||||
Assert.AreEqual(clone.PropertyTypes.Count(), contentType.PropertyTypes.Count());
|
||||
Assert.AreEqual(0, ((ContentTypeBase)clone).NonGroupedPropertyTypes.Count());
|
||||
for (var index = 0; index < contentType.PropertyTypes.Count(); index++)
|
||||
{
|
||||
Assert.AreNotSame(clone.PropertyTypes.ElementAt(index), contentType.PropertyTypes.ElementAt(index));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class PreValueCollectionTests
|
||||
{
|
||||
[Test]
|
||||
public void Can_Deep_Clone()
|
||||
{
|
||||
var d = new PreValueCollection(new Dictionary<string, PreValue>
|
||||
{
|
||||
{"blah1", new PreValue(1, "test1", 1)},
|
||||
{"blah2", new PreValue(2, "test1", 3)},
|
||||
{"blah3", new PreValue(3, "test1", 2)}
|
||||
});
|
||||
|
||||
var a = new PreValueCollection(new[]
|
||||
{
|
||||
new PreValue(1, "test1", 1),
|
||||
new PreValue(2, "test1", 3),
|
||||
new PreValue(3, "test1", 2)
|
||||
});
|
||||
|
||||
var clone1 = (PreValueCollection)d.DeepClone();
|
||||
var clone2 = (PreValueCollection)a.DeepClone();
|
||||
|
||||
Action<PreValueCollection, PreValueCollection> assert = (orig, clone) =>
|
||||
{
|
||||
Assert.AreNotSame(orig, clone);
|
||||
var oDic = orig.FormatAsDictionary();
|
||||
var cDic = clone.FormatAsDictionary();
|
||||
Assert.AreEqual(oDic.Keys.Count(), cDic.Keys.Count());
|
||||
foreach (var k in oDic.Keys)
|
||||
{
|
||||
Assert.AreNotSame(oDic[k], cDic[k]);
|
||||
Assert.AreEqual(oDic[k].Id, cDic[k].Id);
|
||||
Assert.AreEqual(oDic[k].SortOrder, cDic[k].SortOrder);
|
||||
Assert.AreEqual(oDic[k].Value, cDic[k].Value);
|
||||
}
|
||||
};
|
||||
|
||||
assert(d, clone1);
|
||||
assert(a, clone2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,12 @@ using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Serialization;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class PropertyGroupTests
|
||||
public class PropertyGroupTests : BaseUmbracoConfigurationTest
|
||||
{
|
||||
[Test]
|
||||
public void Can_Deep_Clone()
|
||||
@@ -37,7 +38,7 @@ namespace Umbraco.Tests.Models
|
||||
Alias = "test2",
|
||||
CreateDate = DateTime.Now,
|
||||
DataTypeDefinitionId = 6,
|
||||
DataTypeId = Guid.NewGuid(),
|
||||
PropertyEditorAlias = "propTest",
|
||||
Description = "testing2",
|
||||
Key = Guid.NewGuid(),
|
||||
Mandatory = true,
|
||||
@@ -118,7 +119,7 @@ namespace Umbraco.Tests.Models
|
||||
Alias = "test2",
|
||||
CreateDate = DateTime.Now,
|
||||
DataTypeDefinitionId = 6,
|
||||
DataTypeId = Guid.NewGuid(),
|
||||
PropertyEditorAlias = "propTest",
|
||||
Description = "testing2",
|
||||
Key = Guid.NewGuid(),
|
||||
Mandatory = true,
|
||||
|
||||
@@ -364,7 +364,58 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Update_Property_For_Macro()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current))
|
||||
{
|
||||
var macro = repository.Get(1);
|
||||
macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test"));
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Act
|
||||
macro = repository.Get(1);
|
||||
macro.Properties["new1"].Name = "this is a new name";
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(1);
|
||||
Assert.AreEqual("new1", result.Properties.First().Alias);
|
||||
Assert.AreEqual("this is a new name", result.Properties.First().Name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Update_Macro_Property_Alias()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = new MacroRepository(unitOfWork, NullCacheProvider.Current))
|
||||
{
|
||||
var macro = repository.Get(1);
|
||||
macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test"));
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Act
|
||||
macro = repository.Get(1);
|
||||
macro.Properties.UpdateProperty("new1", newAlias: "newAlias");
|
||||
repository.AddOrUpdate(macro);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Assert
|
||||
var result = repository.Get(1);
|
||||
Assert.AreEqual("newAlias", result.Properties.First().Alias);
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
<Compile Include="Models\LanguageTests.cs" />
|
||||
<Compile Include="Models\MemberGroupTests.cs" />
|
||||
<Compile Include="Models\MemberTests.cs" />
|
||||
<Compile Include="Models\PreValueCollectionTests.cs" />
|
||||
<Compile Include="Models\PropertyGroupTests.cs" />
|
||||
<Compile Include="Models\PropertyTypeTests.cs" />
|
||||
<Compile Include="Models\RelationTests.cs" />
|
||||
|
||||
@@ -81,7 +81,7 @@ function dataTypeResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"GetAll")),
|
||||
'Failed to retreive data');
|
||||
'Failed to retrieve data');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ function dataTypeResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"GetEmpty")),
|
||||
'Failed to retreive data for empty datatype');
|
||||
'Failed to retrieve data for empty datatype');
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
|
||||
@@ -146,7 +146,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetByIds",
|
||||
query)),
|
||||
'Failed to retreive entity data for ids ' + ids);
|
||||
'Failed to retrieve entity data for ids ' + ids);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -192,7 +192,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetAll",
|
||||
query)),
|
||||
'Failed to retreive entity data for type ' + type);
|
||||
'Failed to retrieve entity data for type ' + type);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -215,7 +215,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetAncestors",
|
||||
[{id: id}, {type: type}])),
|
||||
'Failed to retreive ancestor data for id ' + id);
|
||||
'Failed to retrieve ancestor data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -238,7 +238,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"GetChildren",
|
||||
[{ id: id }, { type: type }])),
|
||||
'Failed to retreive child data for id ' + id);
|
||||
'Failed to retrieve child data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -271,7 +271,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"Search",
|
||||
[{ query: query }, {type: type}])),
|
||||
'Failed to retreive entity data for query ' + query);
|
||||
'Failed to retrieve entity data for query ' + query);
|
||||
},
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
"entityApiBaseUrl",
|
||||
"SearchAll",
|
||||
[{ query: query }])),
|
||||
'Failed to retreive entity data for query ' + query);
|
||||
'Failed to retrieve entity data for query ' + query);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -99,7 +99,7 @@ function logResource($q, $http, umbRequestHelper) {
|
||||
"logApiBaseUrl",
|
||||
"GetLog",
|
||||
[{ logtype: type, sinceDate: since }])),
|
||||
'Failed to retreive user data for id ' + id);
|
||||
'Failed to retrieve user data for id ' + id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetEmpty")),
|
||||
'Failed to retreive data for empty member item type ' + alias);
|
||||
'Failed to retrieve data for empty member item type ' + alias);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -93,7 +93,7 @@ function stylesheetResource($q, $http, umbRequestHelper) {
|
||||
"stylesheetApiBaseUrl",
|
||||
"GetRulesByName",
|
||||
[{ name: name }])),
|
||||
'Failed to retreive stylesheets ');
|
||||
'Failed to retrieve stylesheets ');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ function treeResource($q, $http, umbRequestHelper) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(getTreeNodesUrl(options.node)),
|
||||
'Failed to retreive data for child nodes ' + options.node.nodeId);
|
||||
'Failed to retrieve data for child nodes ' + options.node.nodeId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2530,9 +2530,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7120</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7130</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7120</IISUrl>
|
||||
<IISUrl>http://localhost:7130</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
@@ -2564,7 +2564,10 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
</Target>
|
||||
<Target Name="BelleBuild" BeforeTargets="Rebuild">
|
||||
<!-- Only runs when a Rebuild is requested -->
|
||||
<Exec WorkingDirectory="$(ProjectDir)\..\..\build\" Command="BuildBelle.bat" ConsoleToMSBuild="true" IgnoreExitCode="true" ContinueOnError="WarnAndContinue" />
|
||||
<ReadLinesFromFile File="$(ProjectDir)\..\..\build\UmbracoVersion.txt">
|
||||
<Output TaskParameter="Lines" PropertyName="VersionNumber" />
|
||||
</ReadLinesFromFile>
|
||||
<Exec WorkingDirectory="$(ProjectDir)\..\..\build\" Command="BuildBelle.bat $(VersionNumber)" ConsoleToMSBuild="true" IgnoreExitCode="true" ContinueOnError="WarnAndContinue" />
|
||||
</Target>
|
||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" />
|
||||
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- SlideShare Settings -->
|
||||
<provider name="SlideShare" type="Umbraco.Web.Media.EmbedProviders.OEmbedRich, umbraco">
|
||||
<urlShemeRegex><![CDATA[slideshare\.net/]]></urlShemeRegex>
|
||||
<apiEndpoint><![CDATA[http://www.slideshare.net/api/oembed/1]]></apiEndpoint>
|
||||
<apiEndpoint><![CDATA[http://www.slideshare.net/api/oembed/2]]></apiEndpoint>
|
||||
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
|
||||
<param name="format">xml</param>
|
||||
</requestParams>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- SlideShare Settings -->
|
||||
<provider name="SlideShare" type="Umbraco.Web.Media.EmbedProviders.OEmbedRich, umbraco">
|
||||
<urlShemeRegex><![CDATA[slideshare\.net/]]></urlShemeRegex>
|
||||
<apiEndpoint><![CDATA[http://www.slideshare.net/api/oembed/1]]></apiEndpoint>
|
||||
<apiEndpoint><![CDATA[http://www.slideshare.net/api/oembed/2]]></apiEndpoint>
|
||||
<requestParams type="Umbraco.Web.Media.EmbedProviders.Settings.Dictionary, umbraco">
|
||||
<param name="format">xml</param>
|
||||
</requestParams>
|
||||
|
||||
@@ -10,21 +10,33 @@ namespace Umbraco.Web.Models
|
||||
{
|
||||
private readonly Dictionary<string, IPublishedProperty> _properties;
|
||||
|
||||
/// <summary>
|
||||
/// Initialized a new instance of the <see cref="DetachedContent"/> class with properties.
|
||||
/// </summary>
|
||||
/// <param name="properties">The properties</param>
|
||||
/// <remarks>Properties must be detached or nested properties ie their property type must be detached or nested.
|
||||
/// Such a detached content can be part of a published property value.</remarks>
|
||||
public DetachedContent(IEnumerable<IPublishedProperty> properties)
|
||||
{
|
||||
_properties = properties.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
// don't uncomment until you know what you are doing
|
||||
/*
|
||||
public DetachedContent(IPublishedContent content)
|
||||
{
|
||||
_properties = content.Properties.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
*/
|
||||
|
||||
// don't uncomment until you know what you are doing
|
||||
// at the moment, I don't fully
|
||||
/*
|
||||
public DetachedContent(IContent content, bool isPreviewing)
|
||||
{
|
||||
var publishedContentType = PublishedContentType.Get(PublishedItemType.Content, content.ContentType.Alias);
|
||||
_properties = PublishedProperty.MapProperties(publishedContentType.PropertyTypes, content.Properties,
|
||||
(t, v) => PublishedProperty.GetDetached(t, v, isPreviewing))
|
||||
(t, v) => PublishedProperty.GetDetached(t.Detached(), v, isPreviewing))
|
||||
.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
@@ -32,7 +44,7 @@ namespace Umbraco.Web.Models
|
||||
{
|
||||
var publishedContentType = PublishedContentType.Get(PublishedItemType.Media, media.ContentType.Alias);
|
||||
_properties = PublishedProperty.MapProperties(publishedContentType.PropertyTypes, media.Properties,
|
||||
(t, v) => PublishedProperty.GetDetached(t, v, isPreviewing))
|
||||
(t, v) => PublishedProperty.GetDetached(t.Detached(), v, isPreviewing))
|
||||
.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
@@ -40,9 +52,10 @@ namespace Umbraco.Web.Models
|
||||
{
|
||||
var publishedContentType = PublishedContentType.Get(PublishedItemType.Member, member.ContentType.Alias);
|
||||
_properties = PublishedProperty.MapProperties(publishedContentType.PropertyTypes, member.Properties,
|
||||
(t, v) => PublishedProperty.GetDetached(t, v, isPreviewing))
|
||||
(t, v) => PublishedProperty.GetDetached(t.Detached(), v, isPreviewing))
|
||||
.ToDictionary(x => x.PropertyTypeAlias, x => x, StringComparer.InvariantCultureIgnoreCase);
|
||||
}
|
||||
*/
|
||||
|
||||
public ICollection<IPublishedProperty> Properties
|
||||
{
|
||||
|
||||
@@ -437,8 +437,9 @@ namespace Umbraco.Web
|
||||
//currently assigned node. The PublishedContentRequest will be null if:
|
||||
// * we are rendering a partial view or child action
|
||||
// * we are rendering a view from a custom route
|
||||
if (UmbracoContext.PublishedContentRequest == null
|
||||
if ((UmbracoContext.PublishedContentRequest == null
|
||||
|| UmbracoContext.PublishedContentRequest.PublishedContent.Id != currentPage.Id)
|
||||
&& currentPage.Id > 0) // in case we're rendering a detached content (id == 0)
|
||||
{
|
||||
item.NodeId = currentPage.Id.ToString();
|
||||
}
|
||||
|
||||
@@ -322,8 +322,6 @@ namespace umbraco.cms.presentation.developer
|
||||
|
||||
void Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
//disable the add validators
|
||||
macroProperties.
|
||||
|
||||
Page.Validate();
|
||||
|
||||
@@ -351,10 +349,14 @@ namespace umbraco.cms.presentation.developer
|
||||
var macroElementType = (DropDownList)item.FindControl("macroPropertyType");
|
||||
|
||||
var prop = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
|
||||
prop.Alias = macroElementAlias.Text.Trim();
|
||||
prop.Name = macroElementName.Text.Trim();
|
||||
prop.EditorAlias = macroElementType.SelectedValue;
|
||||
prop.SortOrder = sort;
|
||||
|
||||
_macro.Properties.UpdateProperty(
|
||||
prop.Alias,
|
||||
macroElementName.Text.Trim(),
|
||||
sort,
|
||||
macroElementType.SelectedValue,
|
||||
macroElementAlias.Text.Trim());
|
||||
|
||||
sort++;
|
||||
}
|
||||
|
||||
|
||||
@@ -887,7 +887,7 @@ namespace umbraco.MacroEngines
|
||||
//this is from SqlMetal and just makes it a bit of fun to allow pluralisation
|
||||
private static string MakePluralName(string name)
|
||||
{
|
||||
if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("ss", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase)))
|
||||
if ((name.EndsWith("x", StringComparison.OrdinalIgnoreCase) || name.EndsWith("ch", StringComparison.OrdinalIgnoreCase)) || (name.EndsWith("s", StringComparison.OrdinalIgnoreCase) || name.EndsWith("sh", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
name = name + "es";
|
||||
return name;
|
||||
|
||||
Reference in New Issue
Block a user