diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs
index 1311593e90..ed9b7c5a9d 100644
--- a/src/Umbraco.Core/DatabaseContext.cs
+++ b/src/Umbraco.Core/DatabaseContext.cs
@@ -303,6 +303,8 @@ namespace Umbraco.Core
connString = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ConnectionString;
}
Initialize(providerName, connString);
+
+ DetermineSqlServerVersion();
}
else if (ConfigurationManager.AppSettings.ContainsKey(GlobalSettings.UmbracoConnectionName) && string.IsNullOrEmpty(ConfigurationManager.AppSettings[GlobalSettings.UmbracoConnectionName]) == false)
{
@@ -339,6 +341,8 @@ namespace Umbraco.Core
//Remove the legacy connection string, so we don't end up in a loop if something goes wrong.
GlobalSettings.RemoveSetting(GlobalSettings.UmbracoConnectionName);
+
+ DetermineSqlServerVersion();
}
else
{
@@ -372,6 +376,49 @@ namespace Umbraco.Core
Initialize(providerName);
}
+ ///
+ /// Set the lazy resolution of determining the SQL server version if that is the db type we're using
+ ///
+ private void DetermineSqlServerVersion()
+ {
+
+ var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
+ if (sqlServerSyntax != null)
+ {
+ //this will not execute now, it is lazy so will only execute when we need to actually know
+ // the sql server version.
+ sqlServerSyntax.VersionName = new Lazy(() =>
+ {
+ try
+ {
+ var database = this._factory.CreateDatabase();
+
+ var version = database.ExecuteScalar("SELECT SERVERPROPERTY('productversion')");
+ var firstPart = version.Split('.')[0];
+ switch (firstPart)
+ {
+ case "11":
+ return SqlServerVersionName.V2012;
+ case "10":
+ return SqlServerVersionName.V2008;
+ case "9":
+ return SqlServerVersionName.V2005;
+ case "8":
+ return SqlServerVersionName.V2000;
+ case "7":
+ return SqlServerVersionName.V7;
+ default:
+ return SqlServerVersionName.Other;
+ }
+ }
+ catch (Exception)
+ {
+ return SqlServerVersionName.Invalid;
+ }
+ });
+ }
+ }
+
internal DatabaseSchemaResult ValidateDatabaseSchema()
{
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
@@ -463,6 +510,8 @@ namespace Umbraco.Core
message = message + "Upgrade completed!
";
}
+ //now that everything is done, we need to determine the version of SQL server that is executing
+
LogHelper.Info("Database configuration status: " + message);
return new Result { Message = message, Success = true, Percentage = "100" };
diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs
index 4a2fd8c289..8fb94e8c0c 100644
--- a/src/Umbraco.Core/Models/PropertyExtensions.cs
+++ b/src/Umbraco.Core/Models/PropertyExtensions.cs
@@ -15,7 +15,12 @@ namespace Umbraco.Core.Models
/// Xml of the property and its value
public static XElement ToXml(this Property property)
{
- string nodeName = UmbracoSettings.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
+ return property.ToXml(ApplicationContext.Current.Services.DataTypeService);
+ }
+
+ internal static XElement ToXml(this Property property, IDataTypeService dataTypeService)
+ {
+ var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
var xd = new XmlDocument();
var xmlNode = xd.CreateNode(XmlNodeType.Element, nodeName, "");
@@ -37,6 +42,16 @@ namespace Umbraco.Core.Models
//var dataType = ApplicationContext.Current.Services.DataTypeService.GetDataTypeDefinitionById(property.PropertyType.DataTypeDefinitionId);
//if (dataType == null) throw new InvalidOperationException("No data type definition found with id " + property.PropertyType.DataTypeDefinitionId);
+ //We've already got the value for the property so we're going to give it to the
+ // data type's data property so it doesn't go re-look up the value from the db again.
+ var defaultData = dt.Data as IDataValueSetter;
+ if (defaultData != null)
+ {
+ defaultData.SetValue(property.Value, property.PropertyType.DataTypeDatabaseType.ToString());
+ }
+
+ xmlNode.AppendChild(dt.Data.ToXMl(xd));
+
var propertyEditor = PropertyEditorResolver.Current.GetById(property.PropertyType.DataTypeId);
if (propertyEditor != null)
{
diff --git a/src/Umbraco.Core/Models/PropertyTypeExtensions.cs b/src/Umbraco.Core/Models/PropertyTypeExtensions.cs
index 62a6a6fd1d..fef05e5e47 100644
--- a/src/Umbraco.Core/Models/PropertyTypeExtensions.cs
+++ b/src/Umbraco.Core/Models/PropertyTypeExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using Umbraco.Core.Services;
using umbraco.interfaces;
namespace Umbraco.Core.Models
@@ -10,6 +11,7 @@ namespace Umbraco.Core.Models
///
/// PropertyType that references a DataType
/// Id of the Property which references this DataType through its PropertyType
+ ///
///
///
/// This extension method is left internal because we don't want to take
@@ -17,10 +19,10 @@ namespace Umbraco.Core.Models
/// be replaced by PropertyEditors. It is however needed to generate xml
/// for a property/propertytype when publishing.
///
- internal static IDataType DataType(this PropertyType propertyType, int propertyId)
+ internal static IDataType DataType(this PropertyType propertyType, int propertyId, IDataTypeService dataTypeService)
{
Mandate.ParameterNotNull(propertyType, "propertyType");
- var dataType = ApplicationContext.Current.Services.DataTypeService.GetDataTypeById(propertyType.DataTypeId);
+ var dataType = dataTypeService.GetDataTypeById(propertyType.DataTypeId);
if (dataType == null)
throw new InvalidOperationException("No IDataType found for control ID " + propertyType.DataTypeId);
diff --git a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs
index c962224689..eb10bf7f87 100644
--- a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs
+++ b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs
@@ -51,7 +51,10 @@ namespace Umbraco.Core.Persistence
try
{
- if (SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
+ //if it is sql ce or it is a sql server version less than 2008, we need to do individual inserts.
+ var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
+ if ((sqlServerSyntax != null && (int)sqlServerSyntax.VersionName.Value < (int)SqlServerVersionName.V2008)
+ || SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
{
//SqlCe doesn't support bulk insert statements!
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index acbc97d445..ed031d9ab0 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -339,19 +339,22 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
+ //Look up (newest) entries by id in cmsDocument table to set newest = false
+ //NOTE: This should only be done for all other versions then the current one, so we don't cause the same entry to be updated multiple times.
+ var documentDtos =
+ Database.Query(
+ "WHERE nodeId = @Id AND newest = @IsNewest AND NOT(versionId = @VersionId)",
+ new {Id = entity.Id, IsNewest = true, VersionId = dto.ContentVersionDto.VersionId});
+ foreach (var documentDto in documentDtos)
+ {
+ var docDto = documentDto;
+ docDto.Newest = false;
+ Database.Update(docDto);
+ }
+
var contentVersionDto = dto.ContentVersionDto;
if (shouldCreateNewVersion)
{
- //Look up (newest) entries by id in cmsDocument table to set newest = false
- //NOTE: This is only relevant when a new version is created, which is why its done inside this if-statement.
- var documentDtos = Database.Fetch("WHERE nodeId = @Id AND newest = @IsNewest", new { Id = entity.Id, IsNewest = true });
- foreach (var documentDto in documentDtos)
- {
- var docDto = documentDto;
- docDto.Newest = false;
- Database.Update(docDto);
- }
-
//Create a new version - cmsContentVersion
//Assumes a new Version guid and Version date (modified date) has been set
Database.Insert(contentVersionDto);
diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs
index 2de2209ab4..3e37674ddf 100644
--- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs
+++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs
@@ -13,6 +13,20 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public static ISqlSyntaxProvider Provider { get { return new SqlServerSyntaxProvider(); } }
}
+ ///
+ /// Represents the version name of SQL server (i.e. the year 2008, 2005, etc...)
+ ///
+ internal enum SqlServerVersionName
+ {
+ Invalid = -1,
+ V7 = 0,
+ V2000 = 1,
+ V2005 = 2,
+ V2008 = 3,
+ V2012 = 4,
+ Other = 5
+ }
+
///
/// Represents an SqlSyntaxProvider for Sql Server
///
@@ -36,6 +50,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
InitColumnTypeMap();
}
+ ///
+ /// Gets/sets the version of the current SQL server instance
+ ///
+ internal Lazy VersionName { get; set; }
+
public override string GetQuotedTableName(string tableName)
{
return string.Format("[{0}]", tableName);
diff --git a/src/Umbraco.Core/Publishing/PublishStatus.cs b/src/Umbraco.Core/Publishing/PublishStatus.cs
index 415b758965..aee9a1fafe 100644
--- a/src/Umbraco.Core/Publishing/PublishStatus.cs
+++ b/src/Umbraco.Core/Publishing/PublishStatus.cs
@@ -8,15 +8,14 @@ namespace Umbraco.Core.Publishing
///
internal class PublishStatus
{
- public IContent ContentItem { get; private set; }
- public PublishStatusType StatusType { get; internal set; }
-
- ///
- /// Gets sets the invalid properties if the status failed due to validation.
- ///
- public IEnumerable InvalidProperties { get; set; }
+ public PublishStatus()
+ {
+ //initialize
+ InvalidProperties = new List();
+ }
public PublishStatus(IContent content, PublishStatusType statusType)
+ : this()
{
ContentItem = content;
StatusType = statusType;
@@ -29,6 +28,13 @@ namespace Umbraco.Core.Publishing
: this(content, PublishStatusType.Success)
{
}
+
+ public IContent ContentItem { get; private set; }
+ public PublishStatusType StatusType { get; internal set; }
+ ///
+ /// Gets sets the invalid properties if the status failed due to validation.
+ ///
+ public IEnumerable InvalidProperties { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs
index 67cff98ac4..1cee710f19 100644
--- a/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs
+++ b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs
@@ -1,4 +1,6 @@
-using System.Web.Security;
+using System;
+using System.Web;
+using System.Web.Security;
using Newtonsoft.Json;
namespace Umbraco.Core.Security
@@ -15,6 +17,7 @@ namespace Umbraco.Core.Security
: base(ticket)
{
UserData = ticket.UserData;
+ EnsureDeserialized();
}
protected readonly string UserData;
@@ -24,54 +27,33 @@ namespace Umbraco.Core.Security
{
get
{
- EnsureDeserialized();
return DeserializedData.StartContentNode;
}
}
public int StartMediaNode
{
- get
- {
- EnsureDeserialized();
- return DeserializedData.StartMediaNode;
- }
+ get { return DeserializedData.StartMediaNode; }
}
public string[] AllowedApplications
{
- get
- {
- EnsureDeserialized();
- return DeserializedData.AllowedApplications;
- }
+ get { return DeserializedData.AllowedApplications; }
}
public object Id
{
- get
- {
- EnsureDeserialized();
- return DeserializedData.Id;
- }
+ get { return DeserializedData.Id; }
}
public string RealName
{
- get
- {
- EnsureDeserialized();
- return DeserializedData.RealName;
- }
+ get { return DeserializedData.RealName; }
}
public string Culture
{
- get
- {
- EnsureDeserialized();
- return DeserializedData.Culture;
- }
+ get { return DeserializedData.Culture; }
}
//public int SessionTimeout
@@ -85,24 +67,42 @@ namespace Umbraco.Core.Security
public string[] Roles
{
- get
- {
- EnsureDeserialized();
- return DeserializedData.Roles;
- }
+ get { return DeserializedData.Roles; }
}
+ ///
+ /// This will ensure we only deserialize once
+ ///
+ ///
+ /// For performance reasons, we'll also check if there's an http context available,
+ /// if so, we'll chuck our instance in there so that we only deserialize once per request.
+ ///
protected void EnsureDeserialized()
{
if (DeserializedData != null)
return;
-
+
+ if (HttpContext.Current != null)
+ {
+ //check if we've already done this in this request
+ var data = HttpContext.Current.Items[typeof(UmbracoBackOfficeIdentity)] as UserData;
+ if (data != null)
+ {
+ DeserializedData = data;
+ return;
+ }
+ }
+
if (string.IsNullOrEmpty(UserData))
{
- DeserializedData = new UserData();
- return;
+ throw new NullReferenceException("The " + typeof(UserData) + " found in the ticket cannot be empty");
+ }
+ DeserializedData = JsonConvert.DeserializeObject(UserData);
+
+ if (HttpContext.Current != null)
+ {
+ HttpContext.Current.Items[typeof (UmbracoBackOfficeIdentity)] = DeserializedData;
}
- DeserializedData = JsonConvert.DeserializeObject(UserData);
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs
index 8aabfed80f..37da38126e 100644
--- a/src/Umbraco.Core/Services/ContentService.cs
+++ b/src/Umbraco.Core/Services/ContentService.cs
@@ -1479,7 +1479,12 @@ namespace Umbraco.Core.Services
LogHelper.Info(
string.Format("Content '{0}' with Id '{1}' could not be published because of invalid properties.",
content.Name, content.Id));
- result.Add(new Attempt(false, new PublishStatus(content, PublishStatusType.FailedContentInvalid)));
+ result.Add(
+ new Attempt(false,
+ new PublishStatus(content, PublishStatusType.FailedContentInvalid)
+ {
+ InvalidProperties = ((ContentBase) content).LastInvalidProperties
+ }));
return result;
}
diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs
index a873343158..5de4285469 100644
--- a/src/Umbraco.Core/UriExtensions.cs
+++ b/src/Umbraco.Core/UriExtensions.cs
@@ -13,6 +13,7 @@ namespace Umbraco.Core
///
public static class UriExtensions
{
+
///
/// Checks if the current uri is a back office request
///
@@ -20,11 +21,14 @@ namespace Umbraco.Core
///
internal static bool IsBackOfficeRequest(this Uri url)
{
+
var authority = url.GetLeftPart(UriPartial.Authority);
var afterAuthority = url.GetLeftPart(UriPartial.Query)
.TrimStart(authority)
.TrimStart("/");
+
+
//check if this is in the umbraco back office
return afterAuthority.InvariantStartsWith(GlobalSettings.Path.TrimStart("/"));
}
diff --git a/src/Umbraco.Tests/Models/DataValueSetterTests.cs b/src/Umbraco.Tests/Models/DataValueSetterTests.cs
new file mode 100644
index 0000000000..db59217166
--- /dev/null
+++ b/src/Umbraco.Tests/Models/DataValueSetterTests.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Diagnostics;
+using System.Xml;
+using NUnit.Framework;
+using Rhino.Mocks;
+using Rhino.Mocks.Interfaces;
+using Umbraco.Core.Models;
+using Umbraco.Core.Services;
+using Umbraco.Core.Strings;
+using Umbraco.Tests.TestHelpers;
+using umbraco.cms.businesslogic.datatype;
+using umbraco.interfaces;
+
+namespace Umbraco.Tests.Models
+{
+ [TestFixture]
+ public class DataValueSetterTests : BaseUmbracoApplicationTest
+ {
+ protected override void FreezeResolution()
+ {
+ ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper());
+ base.FreezeResolution();
+ }
+
+ [Test]
+ public void LoadValueFromDatabase_Is_Not_Called_When_SetValue_Is_Used()
+ {
+ // Arrange
+ var baseDataType = MockRepository.GenerateStub();
+ var dataTypeData = MockRepository.GenerateMock(baseDataType);
+ dataTypeData.Stub(x => x.Value).CallOriginalMethod(OriginalCallOptions.NoExpectation);
+
+ // Act
+
+ ((IDataValueSetter)dataTypeData).SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString());
+ var val = dataTypeData.Value;
+
+ // Assert
+
+ dataTypeData.AssertWasNotCalled(data => data.LoadValueFromDatabase());
+ }
+
+ [Test]
+ public void LoadValueFromDatabase_Is_Called_When_SetValue_Is_Not_Used()
+ {
+ // Arrange
+ var baseDataType = MockRepository.GenerateStub();
+ var dataTypeData = MockRepository.GenerateMock(baseDataType);
+ dataTypeData
+ .Stub(data => data.LoadValueFromDatabase()).WhenCalled(invocation => Debug.WriteLine("asdf"));
+ dataTypeData.Stub(x => x.Value).CallOriginalMethod(OriginalCallOptions.NoExpectation);
+
+ // Act
+
+ var val = dataTypeData.Value;
+
+ // Assert
+
+ dataTypeData.AssertWasCalled(data => data.LoadValueFromDatabase());
+ }
+
+ [Test]
+ public void SetValue_Is_Called_When_Executing_ToXml_On_A_Property_With_DataType_That_Implements_IDataValueSetter()
+ {
+ // Arrange
+ var dataTypeId = Guid.NewGuid();
+
+ var dataTypeData = MockRepository.GenerateMock();
+ dataTypeData
+ .Stub(data => data.ToXMl(Arg.Is.Anything))
+ .Return(null) // you have to call Return() even though we're about to override it
+ .WhenCalled(invocation =>
+ {
+ var xmlDoc = (XmlDocument) invocation.Arguments[0];
+ invocation.ReturnValue = xmlDoc.CreateElement("test");
+ });
+
+ var dataType = MockRepository.GenerateStub();
+ dataType.Stub(type => type.Data).Return(dataTypeData);
+
+ var dataTypeSvc = MockRepository.GenerateStub();
+ dataTypeSvc.Stub(service => service.GetDataTypeById(dataTypeId)).Return(dataType);
+
+ var property = new Property(
+ 1234,
+ Guid.NewGuid(),
+ new PropertyType(dataTypeId, DataTypeDatabaseType.Nvarchar)
+ {
+ Alias = "test"
+ }, "Hello world");
+
+ // Act
+
+ var xml = property.ToXml(dataTypeSvc);
+
+ // Assert
+
+ ((IDataValueSetter)dataTypeData).AssertWasCalled(setter => setter.SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString()));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Services/PackagingServiceTests.cs b/src/Umbraco.Tests/Services/PackagingServiceTests.cs
new file mode 100644
index 0000000000..abdfb2f9f3
--- /dev/null
+++ b/src/Umbraco.Tests/Services/PackagingServiceTests.cs
@@ -0,0 +1,41 @@
+using System;
+using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+using Umbraco.Tests.TestHelpers.Entities;
+
+namespace Umbraco.Tests.Services
+{
+ //[TestFixture]
+ //public class PackagingServiceTests : BaseServiceTest
+ //{
+ // [Test]
+ // public void Export_Content()
+ // {
+ // var yesNo = DataTypesResolver.Current.GetById(new Guid(Constants.PropertyEditors.TrueFalse));
+ // var txtField = DataTypesResolver.Current.GetById(new Guid(Constants.PropertyEditors.Textbox));
+
+ // var contentWithDataType = MockedContentTypes.CreateSimpleContentType(
+ // "test",
+ // "Test",
+ // new PropertyTypeCollection(
+ // new PropertyType[]
+ // {
+ // new PropertyType(new DataTypeDefinition(-1, txtField.Id)
+ // {
+ // Name = "Testing Textfield", DatabaseType = DataTypeDatabaseType.Ntext
+ // }),
+ // new PropertyType(new DataTypeDefinition(-1, yesNo.Id)
+ // {
+ // Name = "Testing intfield", DatabaseType = DataTypeDatabaseType.Integer
+ // })
+ // }));
+
+ // var content = MockedContent.CreateSimpleContent(contentWithDataType);
+ // content.Name = "Test";
+
+ // var exported = ServiceContext.PackagingService.Export(content);
+
+ // }
+ //}
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs
index 7e453ca3c2..dd75809a5f 100644
--- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs
+++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs
@@ -42,28 +42,39 @@ namespace Umbraco.Tests.TestHelpers
private static volatile bool _firstRunInTestSession = true;
private static readonly object Locker = new object();
private bool _firstTestInFixture = true;
- private DefaultDatabaseFactory _dbFactory;
//Used to flag if its the first test in the current session
private bool _isFirstRunInTestSession = false;
//Used to flag if its the first test in the current fixture
private bool _isFirstTestInFixture = false;
+ private ApplicationContext _appContext;
+
[SetUp]
public override void Initialize()
{
InitializeFirstRunFlags();
-
- _dbFactory = new DefaultDatabaseFactory(
- GetDbConnectionString(),
- GetDbProviderName());
-
- base.Initialize();
-
+
var path = TestHelper.CurrentAssemblyDirectory;
AppDomain.CurrentDomain.SetData("DataDirectory", path);
- DatabaseContext.Initialize(_dbFactory.ProviderName, _dbFactory.ConnectionString);
+ var dbFactory = new DefaultDatabaseFactory(
+ GetDbConnectionString(),
+ GetDbProviderName());
+ _appContext = new ApplicationContext(
+ //assign the db context
+ new DatabaseContext(dbFactory),
+ //assign the service context
+ new ServiceContext(new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy()),
+ //disable cache
+ false)
+ {
+ IsReady = true
+ };
+
+ base.Initialize();
+
+ DatabaseContext.Initialize(dbFactory.ProviderName, dbFactory.ConnectionString);
CreateSqlCeDatabase();
@@ -75,18 +86,7 @@ namespace Umbraco.Tests.TestHelpers
protected override void SetupApplicationContext()
{
- //disable cache
- var cacheHelper = new CacheHelper(new NullCacheProvider(), false);
-
- ApplicationContext.Current = new ApplicationContext(
- //assign the db context
- new DatabaseContext(_dbFactory),
- //assign the service context
- new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy(), cacheHelper),
- cacheHelper)
- {
- IsReady = true
- };
+ ApplicationContext.Current = _appContext;
}
///
diff --git a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs
index 677a425fa9..76fc4917f6 100644
--- a/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs
+++ b/src/Umbraco.Tests/TestHelpers/BaseUmbracoApplicationTest.cs
@@ -33,6 +33,7 @@ namespace Umbraco.Tests.TestHelpers
SetupPluginManager();
SetupApplicationContext();
InitializeMappers();
+
FreezeResolution();
}
@@ -48,7 +49,7 @@ namespace Umbraco.Tests.TestHelpers
ApplicationContext.Current = null;
ResetPluginManager();
}
-
+
private void InitializeMappers()
{
Mapper.Initialize(configuration =>
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index de74ccf7ad..9245eca8f5 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -198,10 +198,12 @@
+
+
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 92b5e584bf..75408644a6 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -937,6 +937,7 @@
+
@@ -957,6 +958,7 @@
+
@@ -979,6 +981,7 @@
+
@@ -998,6 +1001,7 @@
+
@@ -1050,6 +1054,7 @@
+
@@ -1079,6 +1084,7 @@
+
@@ -1112,6 +1118,7 @@
+
@@ -1161,6 +1168,7 @@
+
@@ -1191,6 +1199,7 @@
+
@@ -1215,6 +1224,7 @@
+
@@ -1244,6 +1254,7 @@
+
@@ -1267,6 +1278,7 @@
+
@@ -1281,8 +1293,12 @@
+
+
+
+
@@ -1291,6 +1307,8 @@
+
+
@@ -1299,8 +1317,12 @@
+
+
+
+
@@ -1308,8 +1330,10 @@
+
+
@@ -1318,6 +1342,7 @@
+
@@ -1333,6 +1358,8 @@
+
+
@@ -1374,6 +1401,7 @@
+
diff --git a/src/Umbraco.Web.UI/config/metablogConfig.config b/src/Umbraco.Web.UI/config/metablogConfig.config
index 83cc2c1aa1..5621dbee75 100644
--- a/src/Umbraco.Web.UI/config/metablogConfig.config
+++ b/src/Umbraco.Web.UI/config/metablogConfig.config
@@ -5,7 +5,7 @@
0
1080
False
- Home
+ Base
@@ -14,6 +14,6 @@
-
+
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/umbraco/controls/passwordChanger.ascx b/src/Umbraco.Web.UI/umbraco/controls/passwordChanger.ascx
index fccd948dec..b9da0cbac7 100644
--- a/src/Umbraco.Web.UI/umbraco/controls/passwordChanger.ascx
+++ b/src/Umbraco.Web.UI/umbraco/controls/passwordChanger.ascx
@@ -1,16 +1,34 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="passwordChanger.ascx.cs" Inherits="umbraco.controls.passwordChanger" %>
-Change password
+
-
-
- | <%=umbraco.ui.GetText("user", "newPassword")%>: |
-
- |
- | <%=umbraco.ui.GetText("user", "confirmNewPassword")%>: |
-
-
- |
-
-
\ No newline at end of file
+Change password
+
+
diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs
index 4210fc1e3e..e545e65311 100644
--- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs
+++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs
@@ -51,14 +51,6 @@ namespace Umbraco.Web.UI.Pages
Response.Redirect(SystemDirectories.Umbraco + "/logout.aspx?redir=" + Server.UrlEncode(Request.RawUrl), true);
}
}
-
- protected override void OnInit(EventArgs e)
- {
- base.OnInit(e);
-
- System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(ui.Culture(Security.CurrentUser));
- System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
- }
///
/// Gets/sets the app that this page is assigned to
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
index ab8579db27..91c6a8a4e0 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
@@ -249,7 +249,7 @@ namespace umbraco.cms.presentation
//update UI and set document properties
PerformSaveLogic();
-
+
//persist the document
_document.Save();
@@ -257,7 +257,7 @@ namespace umbraco.cms.presentation
BusinessLogic.Actions.Action.RunActionHandlers(_document, ActionUpdate.Instance);
ClientTools.ShowSpeechBubble(
- speechBubbleIcon.save, ui.Text("speechBubbles", "editContentSavedHeader", null),
+ speechBubbleIcon.save, ui.Text("speechBubbles", "editContentSavedHeader", null),
ui.Text("speechBubbles", "editContentSavedText", null));
ClientTools.SyncTree(_document.Path, true);
@@ -291,7 +291,7 @@ namespace umbraco.cms.presentation
{
//update UI and set document properties
PerformSaveLogic();
-
+
//the business logic here will check to see if the doc can actually be published and will return the
// appropriate result so we can display the correct error messages (or success).
var savePublishResult = _document.SaveAndPublishWithResult(UmbracoUser);
@@ -309,7 +309,7 @@ namespace umbraco.cms.presentation
_documentHasPublishedVersion = _document.Content.HasPublishedVersion();
}
-
+
ClientTools.SyncTree(_document.Path, true);
}
@@ -320,8 +320,8 @@ namespace umbraco.cms.presentation
case PublishStatusType.Success:
case PublishStatusType.SuccessAlreadyPublished:
ClientTools.ShowSpeechBubble(
- speechBubbleIcon.save,
- ui.Text("speechBubbles", "editContentPublishedHeader", UmbracoUser),
+ speechBubbleIcon.save,
+ ui.Text("speechBubbles", "editContentPublishedHeader", UmbracoUser),
ui.Text("speechBubbles", "editContentPublishedText", UmbracoUser));
break;
case PublishStatusType.FailedPathNotPublished:
@@ -550,23 +550,40 @@ namespace umbraco.cms.presentation
}
menuItem.ImageURL = SystemDirectories.Umbraco + "/images/editor/vis.gif";
- // Fix for U4-682, if there's no template, disable the preview button
- if (_document.Template != -1)
+
+ if (EnablePreviewButton())
{
menuItem.AltText = ui.Text("buttons", "showPage", UmbracoUser);
menuItem.OnClickCommand = "window.open('dialogs/preview.aspx?id=" + id + "','umbPreview')";
}
else
{
- string showPageDisabledText = ui.Text("buttons", "showPageDisabled", UmbracoUser);
+ var showPageDisabledText = ui.Text("buttons", "showPageDisabled", UmbracoUser);
if (showPageDisabledText.StartsWith("["))
- showPageDisabledText = ui.GetText("buttons", "showPageDisabled", null, "en"); ;
+ showPageDisabledText = ui.GetText("buttons", "showPageDisabled", null, "en");
menuItem.AltText = showPageDisabledText;
- ((Image)menuItem).Attributes.Add("style", "opacity: 0.5");
+ ((Image) menuItem).Attributes.Add("style", "opacity: 0.5");
}
}
+ private bool EnablePreviewButton()
+ {
+ // Fix for U4-862, if there's no template, disable the preview button
+ // Fixed again for U4-2587, apparently at some point "no template" changed from -1 to 0? -SJ
+ // Now also catches when template doesn't exist any more or is not allowed any more
+ // Don't think there's a better way to check if the template exists besides trying to instantiate it..
+ try
+ {
+ var template = new businesslogic.template.Template(_document.Template);
+ // If template is found check if it's in the list of allowed templates for this document
+ return _document.Content.ContentType.AllowedTemplates.ToList().Any(t => t.Id == template.Id);
+ }
+ catch (Exception) { }
+
+ return false;
+ }
+
///
/// JsInclude1 control.
///
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
index 55303bc219..1569a2d110 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
@@ -348,16 +348,12 @@ namespace umbraco.cms.presentation.user
}
}
}
-
- #region Web Form Designer generated code
-
+
protected override void OnInit(EventArgs e)
{
- //
- // CODEGEN: This call is required by the ASP.NET Web Form Designer.
- //
- InitializeComponent();
- base.OnInit(e);
+ //lapps.SelectionMode = ListSelectionMode.Multiple;
+ lapps.RepeatLayout = RepeatLayout.Flow;
+ lapps.RepeatDirection = RepeatDirection.Vertical;
}
protected override void OnPreRender(EventArgs e)
@@ -366,23 +362,9 @@ namespace umbraco.cms.presentation.user
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/CMSNode.asmx"));
// ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx"));
-
-
+
}
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- //lapps.SelectionMode = ListSelectionMode.Multiple;
- lapps.RepeatLayout = RepeatLayout.Flow;
- lapps.RepeatDirection = RepeatDirection.Vertical;
- }
-
- #endregion
-
///
/// Handles the Click event of the saveUser control.
///
diff --git a/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs b/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs
index 9594b84b07..dd09265713 100644
--- a/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs
+++ b/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs
@@ -115,9 +115,6 @@ namespace umbraco.BasePages
else
Response.Redirect(SystemDirectories.Umbraco + "/logout.aspx?redir=" + Server.UrlEncode(Request.RawUrl), true);
}
-
- System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(ui.Culture(this.getUser()));
- System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
}
}
}
\ No newline at end of file
diff --git a/src/umbraco.cms/businesslogic/ContentType.cs b/src/umbraco.cms/businesslogic/ContentType.cs
index ebacf89fa1..71d676f54d 100644
--- a/src/umbraco.cms/businesslogic/ContentType.cs
+++ b/src/umbraco.cms/businesslogic/ContentType.cs
@@ -70,7 +70,7 @@ namespace umbraco.cms.businesslogic
_alias = alias;
_iconurl = icon;
_thumbnail = thumbnail;
-
+
if (masterContentType.HasValue)
MasterContentType = masterContentType.Value;
@@ -92,7 +92,7 @@ namespace umbraco.cms.businesslogic
allowAtRoot, isContainer, Alias,icon,thumbnail,description
FROM umbracoNode INNER JOIN cmsContentType ON umbracoNode.id = cmsContentType.nodeId
WHERE nodeObjectType = @nodeObjectType";
-
+
#endregion
#region Static Methods
@@ -113,12 +113,12 @@ namespace umbraco.cms.businesslogic
///
internal static IDictionary GetAliasesAndNames(string contentTypeAlias)
{
- return AliasToNames.GetOrAdd(contentTypeAlias, s =>
- {
- var ct = GetByAlias(contentTypeAlias);
- var userFields = ct.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name);
- return userFields;
- });
+ return AliasToNames.GetOrAdd(contentTypeAlias, s =>
+ {
+ var ct = GetByAlias(contentTypeAlias);
+ var userFields = ct.PropertyTypes.ToDictionary(x => x.Alias, x => x.Name);
+ return userFields;
+ });
}
///
@@ -150,21 +150,21 @@ namespace umbraco.cms.businesslogic
//propertyTypeAlias needs to be invariant, so we will store uppercase
var key = new System.Tuple(contentTypeAlias, propertyTypeAlias.ToUpper());
-
+
return PropertyTypeCache.GetOrAdd(
key,
tuple =>
- {
- // With 4.10 we can't do this via direct SQL as we have content type mixins
- var controlId = Guid.Empty;
- var ct = GetByAlias(contentTypeAlias);
+ {
+ // With 4.10 we can't do this via direct SQL as we have content type mixins
+ var controlId = Guid.Empty;
+ var ct = GetByAlias(contentTypeAlias);
var pt = ct.getPropertyType(propertyTypeAlias);
if (pt != null)
{
controlId = pt.DataTypeDefinition.DataType.Id;
}
- return controlId;
- });
+ return controlId;
+ });
}
///
@@ -244,7 +244,7 @@ namespace umbraco.cms.businesslogic
private bool _isContainerContentType;
private List _allowedChildContentTypeIDs;
private List _virtualTabs;
-
+
protected internal IContentTypeComposition ContentTypeItem;
#endregion
@@ -264,7 +264,7 @@ namespace umbraco.cms.businesslogic
foreach (var i in GetContentIdsForContentType())
{
RebuildXmlStructureForContentItem(i);
- }
+ }
}
///
@@ -292,7 +292,7 @@ namespace umbraco.cms.businesslogic
dr.Close();
}
return ids;
- }
+ }
///
/// Rebuilds the xml structure for the content item by id
@@ -325,7 +325,7 @@ namespace umbraco.cms.businesslogic
INNER JOIN cmsContentType ON cmsContent.contentType = cmsContentType.nodeId
WHERE cmsContentType.nodeId = @nodeId)",
SqlHelper.CreateParameter("@nodeId", this.Id));
- }
+ }
#endregion
@@ -443,7 +443,7 @@ namespace umbraco.cms.businesslogic
}
}
}
-
+
///
/// Gets or sets the description.
///
@@ -580,41 +580,41 @@ namespace umbraco.cms.businesslogic
cacheKey,
TimeSpan.FromMinutes(15),
() =>
+ {
+ //MCH NOTE: For the timing being I have changed this to a dictionary to ensure that property types
+ //aren't added multiple times through the MasterContentType structure, because each level loads
+ //its own + inherited property types, which is wrong. Once we are able to fully switch to the new api
+ //this should no longer be a problem as the composition always contains a correct list of property types.
+ var result = new Dictionary();
+ using (IRecordsReader dr =
+ SqlHelper.ExecuteReader(
+ "select id from cmsPropertyType where contentTypeId = @ctId order by sortOrder",
+ SqlHelper.CreateParameter("@ctId", Id)))
{
- //MCH NOTE: For the timing being I have changed this to a dictionary to ensure that property types
- //aren't added multiple times through the MasterContentType structure, because each level loads
- //its own + inherited property types, which is wrong. Once we are able to fully switch to the new api
- //this should no longer be a problem as the composition always contains a correct list of property types.
- var result = new Dictionary();
- using (IRecordsReader dr =
- SqlHelper.ExecuteReader(
- "select id from cmsPropertyType where contentTypeId = @ctId order by sortOrder",
- SqlHelper.CreateParameter("@ctId", Id)))
+ while (dr.Read())
{
- while (dr.Read())
+ int id = dr.GetInt("id");
+ PropertyType pt = PropertyType.GetPropertyType(id);
+ if (pt != null)
+ result.Add(pt.Id, pt);
+ }
+ }
+
+ // Get Property Types from the master content type
+ if (MasterContentTypes.Count > 0)
+ {
+ foreach (var mct in MasterContentTypes)
+ {
+ var pts = GetContentType(mct).PropertyTypes;
+ foreach (var pt in pts)
{
- int id = dr.GetInt("id");
- PropertyType pt = PropertyType.GetPropertyType(id);
- if (pt != null)
+ if (result.ContainsKey(pt.Id) == false)
result.Add(pt.Id, pt);
}
}
-
- // Get Property Types from the master content type
- if (MasterContentTypes.Count > 0)
- {
- foreach (var mct in MasterContentTypes)
- {
- var pts = GetContentType(mct).PropertyTypes;
- foreach (var pt in pts)
- {
- if (result.ContainsKey(pt.Id) == false)
- result.Add(pt.Id, pt);
- }
- }
- }
- return result.Select(x => x.Value).ToList();
- });
+ }
+ return result.Select(x => x.Value).ToList();
+ });
}
}
@@ -850,7 +850,7 @@ namespace umbraco.cms.businesslogic
foreach (var i in value)
{
int id = i;
- list.Add(new ContentTypeSort{Id = new Lazy(() => id), SortOrder = sort});
+ list.Add(new ContentTypeSort { Id = new Lazy(() => id), SortOrder = sort });
sort++;
}
@@ -963,7 +963,7 @@ namespace umbraco.cms.businesslogic
{
ContentTypeItem.RemovePropertyType(pt.Alias);
}
-
+
// Remove from cache
FlushFromCache(Id);
}
@@ -1163,7 +1163,7 @@ namespace umbraco.cms.businesslogic
///
/// The id.
public static void FlushFromCache(int id)
- {
+ {
//Ensure that MediaTypes are reloaded from db by clearing cache
InMemoryCacheProvider.Current.Clear();
@@ -1428,12 +1428,12 @@ namespace umbraco.cms.businesslogic
public List GetAllPropertyTypes()
{
var db = ApplicationContext.Current.DatabaseContext.Database;
- var propertyTypeDtos = db.Fetch("WHERE propertyTypeGroupId = @Id", new {Id = _id});
+ var propertyTypeDtos = db.Fetch("WHERE propertyTypeGroupId = @Id", new { Id = _id });
var tmp = propertyTypeDtos
.Select(propertyTypeDto => PropertyType.GetPropertyType(propertyTypeDto.Id))
.ToList();
- var propertyTypeGroupDtos = db.Fetch("WHERE parentGroupId = @Id", new {Id = _id});
+ var propertyTypeGroupDtos = db.Fetch("WHERE parentGroupId = @Id", new { Id = _id });
foreach (var propertyTypeGroupDto in propertyTypeGroupDtos)
{
var inheritedPropertyTypeDtos = db.Fetch("WHERE propertyTypeGroupId = @Id", new { Id = propertyTypeGroupDto.Id });
@@ -1504,6 +1504,24 @@ namespace umbraco.cms.businesslogic
}
}
+ ///
+ /// Gets the tab caption by id.
+ ///
+ /// The id.
+ ///
+ internal static string GetRawCaptionById(int id)
+ {
+ try
+ {
+ var tempCaption = SqlHelper.ExecuteScalar("Select text from cmsPropertyTypeGroup where id = " + id);
+ return tempCaption;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
private readonly int _id;
private int? _sortOrder;
@@ -1629,7 +1647,7 @@ namespace umbraco.cms.businesslogic
{
if (!_caption.StartsWith("#"))
return _caption;
-
+
var lang = Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name);
if (lang != null)
{
@@ -1645,6 +1663,5 @@ namespace umbraco.cms.businesslogic
}
}
#endregion
-
}
}
diff --git a/src/umbraco.cms/businesslogic/datatype/DefaultData.cs b/src/umbraco.cms/businesslogic/datatype/DefaultData.cs
index 8c09d6db0c..876d05da06 100644
--- a/src/umbraco.cms/businesslogic/datatype/DefaultData.cs
+++ b/src/umbraco.cms/businesslogic/datatype/DefaultData.cs
@@ -15,7 +15,7 @@ namespace umbraco.cms.businesslogic.datatype
/// Default implementation of the IData interface that stores data inside the Umbraco database.
///
[Obsolete("This class is no longer used and will be removed from the codebase in the future.")]
- public class DefaultData : IData, IDataWithPreview
+ public class DefaultData : IData, IDataWithPreview, IDataValueSetter
{
private int _propertyId;
private object _value;
@@ -58,10 +58,29 @@ namespace umbraco.cms.businesslogic.datatype
_value = InitValue;
}
+ ///
+ /// This is here for performance reasons since in some cases we will have already resolved the value from the db
+ /// and want to just give this object the value so it doesn't go re-look it up from the database.
+ ///
+ ///
+ ///
+ void IDataValueSetter.SetValue(object val, string strDbType)
+ {
+ _value = val;
+ //now that we've set our value, we can update our BaseDataType object with the correct values from the db
+ //instead of making it query for itself. This is a peformance optimization enhancement.
+ var dbType = BaseDataType.GetDBType(strDbType);
+ var fieldName = BaseDataType.GetDataFieldName(dbType);
+ _dataType.SetDataTypeProperties(fieldName, dbType);
+
+ //ensures that it doesn't go back to the db
+ _valueLoaded = true;
+ }
+
///
/// Loads the data value from the database.
///
- protected virtual void LoadValueFromDatabase()
+ protected internal virtual void LoadValueFromDatabase()
{
var sql = new Sql();
sql.Select("*")
@@ -244,5 +263,7 @@ namespace umbraco.cms.businesslogic.datatype
}
#endregion
+
+
}
}
diff --git a/src/umbraco.cms/businesslogic/web/DocumentType.cs b/src/umbraco.cms/businesslogic/web/DocumentType.cs
index 1a9e203ada..31d5d89e14 100644
--- a/src/umbraco.cms/businesslogic/web/DocumentType.cs
+++ b/src/umbraco.cms/businesslogic/web/DocumentType.cs
@@ -527,7 +527,7 @@ namespace umbraco.cms.businesslogic.web
//Datatype definition guid was added in v4 to enable datatype imports
ptx.AppendChild(XmlHelper.AddTextNode(xd, "Definition", pt.DataTypeDefinition.UniqueId.ToString()));
- ptx.AppendChild(XmlHelper.AddTextNode(xd, "Tab", Tab.GetCaptionById(pt.TabId)));
+ ptx.AppendChild(XmlHelper.AddTextNode(xd, "Tab", Tab.GetRawCaptionById(pt.TabId)));
ptx.AppendChild(XmlHelper.AddTextNode(xd, "Mandatory", pt.Mandatory.ToString()));
ptx.AppendChild(XmlHelper.AddTextNode(xd, "Validation", pt.ValidationRegExp));
ptx.AppendChild(XmlHelper.AddCDataNode(xd, "Description", pt.GetRawDescription()));
diff --git a/src/umbraco.interfaces/IData.cs b/src/umbraco.interfaces/IData.cs
index c0580f0fee..17a374ff05 100644
--- a/src/umbraco.interfaces/IData.cs
+++ b/src/umbraco.interfaces/IData.cs
@@ -3,6 +3,15 @@ using System.Xml;
namespace umbraco.interfaces
{
+ ///
+ /// Internal interface used to decorate any IData that can be optimized when exporting
+ /// XML like in the packaging service. Instead of relying on the IData to go get the value
+ /// from the db, any IData that implements this can have it's value set from the packaging service.
+ ///
+ internal interface IDataValueSetter
+ {
+ void SetValue(object val, string strDbType);
+ }
///
/// The IData is part of the IDataType interface for creating new data types in the umbraco backoffice.
diff --git a/src/umbraco.interfaces/Properties/AssemblyInfo.cs b/src/umbraco.interfaces/Properties/AssemblyInfo.cs
index 06f4dbdf64..709f231e00 100644
--- a/src/umbraco.interfaces/Properties/AssemblyInfo.cs
+++ b/src/umbraco.interfaces/Properties/AssemblyInfo.cs
@@ -9,4 +9,11 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("umbraco.interfaces")]
[assembly: AssemblyDescription("Core assembly containing legacy interfaces")]
[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyProduct("Umbraco CMS")]
\ No newline at end of file
+[assembly: AssemblyProduct("Umbraco CMS")]
+
+[assembly: InternalsVisibleTo("cms")]
+[assembly: InternalsVisibleTo("Umbraco.Core")]
+[assembly: InternalsVisibleTo("Umbraco.Tests")]
+
+//allow this to be mocked in our unit tests
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]