Merge remote-tracking branch 'origin/7.1.4' into 7.1.3-variations

This commit is contained in:
Shannon
2014-05-20 13:30:06 +10:00
41 changed files with 380 additions and 99 deletions
+10 -1
View File
@@ -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
View File
@@ -325,7 +325,7 @@
Regex="CurrentComment { get { return &quot;([a-zA-Z]+)?&quot;"
ReplacementText="CurrentComment { get { return &quot;$(BUILD_COMMENT)&quot;"/>
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.targets"
<XmlPoke XmlInputPath=".\NuSpecs\build\UmbracoCms.props"
Namespaces="&lt;Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' /&gt;"
Query="//x:UmbracoVersion"
Value="$(NewVersion)" />
+2 -1
View File
@@ -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%
+1
View File
@@ -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>
+2 -3
View File
@@ -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>
+4 -4
View File
@@ -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>
+24
View File
@@ -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
}
}
+1
View File
@@ -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.
-23
View File
@@ -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
+31 -6
View File
@@ -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;
}
}
}
+23 -1
View File
@@ -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
+1 -1
View File
@@ -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);
}
}
}
}
+8 -1
View File
@@ -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;
}
}
}
+17 -1
View File
@@ -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++)
+22
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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()
+1
View File
@@ -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);
}
};
}
+6 -3
View File
@@ -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>
+16 -3
View File
@@ -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
{
+2 -1
View File
@@ -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;