From 3a4a6579d3900fba431d219de8d753181fb01f1b Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Fri, 30 Aug 2013 10:40:29 +0200
Subject: [PATCH 01/18] Fixes: U4-2711 DAMP throws unknown exception on image
upload with image cropper
---
src/Umbraco.Core/Models/PropertyExtensions.cs | 2 +-
src/umbraco.editorControls/imagecropper/DataTypeData.cs | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs
index ae01532c87..2ef594c8c2 100644
--- a/src/Umbraco.Core/Models/PropertyExtensions.cs
+++ b/src/Umbraco.Core/Models/PropertyExtensions.cs
@@ -43,7 +43,7 @@ namespace Umbraco.Core.Models
//This seems to fail during testing
//SD: With the new null checks below, this shouldn't fail anymore.
var dt = property.PropertyType.DataType(property.Id, dataTypeService);
- if (dt != null && dt.Data != null)
+ if (dt != null && dt.Data != null && dt.Data.Value != null)
{
//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.
diff --git a/src/umbraco.editorControls/imagecropper/DataTypeData.cs b/src/umbraco.editorControls/imagecropper/DataTypeData.cs
index 7c667aaa24..9c68edb04d 100644
--- a/src/umbraco.editorControls/imagecropper/DataTypeData.cs
+++ b/src/umbraco.editorControls/imagecropper/DataTypeData.cs
@@ -8,14 +8,14 @@ namespace umbraco.editorControls.imagecropper
public override XmlNode ToXMl(XmlDocument data)
{
- if (Value.ToString() != "") {
- XmlDocument xd = new XmlDocument();
+ if (Value != null && Value.ToString() != "")
+ {
+ var xd = new XmlDocument();
xd.LoadXml(Value.ToString());
return data.ImportNode(xd.DocumentElement, true);
- } else {
- return base.ToXMl(data);
}
+ return base.ToXMl(data);
}
}
}
\ No newline at end of file
From d559411187d100243057e53667a5107ea03e467a Mon Sep 17 00:00:00 2001
From: Shannon
Date: Fri, 30 Aug 2013 14:15:51 +1000
Subject: [PATCH 02/18] Fixes U4-2300 6.1.0: Changing a template's parent
causes tree to collapse
---
.../umbraco/settings/editTemplate.aspx | 2 +
.../umbraco_client/Editors/EditTemplate.js | 56 ++++++++++++++-----
.../umbraco_client/Editors/EditView.js | 32 +++++++++--
.../WebServices/SaveFileController.cs | 54 ++++++++++++------
4 files changed, 108 insertions(+), 36 deletions(-)
diff --git a/src/Umbraco.Web.UI/umbraco/settings/editTemplate.aspx b/src/Umbraco.Web.UI/umbraco/settings/editTemplate.aspx
index 1308d96298..84a2579687 100644
--- a/src/Umbraco.Web.UI/umbraco/settings/editTemplate.aspx
+++ b/src/Umbraco.Web.UI/umbraco/settings/editTemplate.aspx
@@ -1,5 +1,6 @@
<%@ Page MasterPageFile="../masterpages/umbracoPage.Master" Language="c#" CodeBehind="EditTemplate.aspx.cs"
ValidateRequest="false" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Umbraco.Settings.EditTemplate" %>
+<%@ Import Namespace="Umbraco.Core" %>
<%@ Import Namespace="Umbraco.Core.IO" %>
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
@@ -19,6 +20,7 @@
jQuery(document).ready(function() {
//create the editor
editor = new Umbraco.Editors.EditTemplate({
+ restServiceLocation: "<%= Url.GetSaveFileServicePath() %>",
umbracoPath: '<%= IOHelper.ResolveUrl(SystemDirectories.Umbraco) %>',
editorClientId: '<%= editorSource.ClientID %>',
useMasterPages: <%=umbraco.UmbracoSettings.UseAspNetMasterPages.ToString().ToLower()%>,
diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js
index c3d142e314..adcf8de50c 100644
--- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js
+++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditTemplate.js
@@ -101,27 +101,57 @@
save: function(templateName, templateAlias, codeVal) {
var self = this;
- umbraco.presentation.webservices.codeEditorSave.SaveTemplate(
- templateName, templateAlias, codeVal, self._opts.templateId, this._opts.masterPageDropDown.val(),
- function(t) { self.submitSucces(t); },
- function(t) { self.submitFailure(t); });
-
+ $.post(self._opts.restServiceLocation + "SaveTemplate",
+ JSON.stringify({
+ templateName: templateName,
+ templateAlias: templateAlias,
+ templateContents: codeVal,
+ templateId: self._opts.templateId,
+ masterTemplateId: this._opts.masterPageDropDown.val()
+ }),
+ function (e) {
+ if (e.success) {
+ self.submitSuccess(e);
+ } else {
+ self.submitFailure(e.message, e.header);
+ }
+ });
+
},
- submitSucces: function(t) {
- if (t != 'true') {
- top.UmbSpeechBubble.ShowMessage('error', this._opts.text.templateErrorHeader, this._opts.text.templateErrorText);
+ submitSuccess: function (args) {
+ var msg = args.message;
+ var header = args.header;
+ var path = this._opts.treeSyncPath;
+ var pathChanged = false;
+ if (args.path) {
+ if (path != args.path) {
+ pathChanged = true;
+ }
+ path = args.path;
+ }
+
+ top.UmbSpeechBubble.ShowMessage('save', header, msg);
+ UmbClientMgr.mainTree().setActiveTreeType('templates');
+ if (pathChanged) {
+ UmbClientMgr.mainTree().moveNode(this._opts.templateId, path);
}
else {
- top.UmbSpeechBubble.ShowMessage('save', this._opts.text.templateSavedHeader, this._opts.text.templateSavedText);
+ UmbClientMgr.mainTree().syncTree(path, true);
}
- UmbClientMgr.mainTree().setActiveTreeType('templates');
- UmbClientMgr.mainTree().syncTree(this._opts.treeSyncPath, true);
},
- submitFailure: function(t) {
- top.UmbSpeechBubble.ShowMessage('error', this._opts.text.templateErrorHeader, this._opts.text.templateErrorText);
+ submitFailure: function (err, header) {
+ top.UmbSpeechBubble.ShowMessage('error', header, err);
}
});
+
+ //Set defaults for jQuery ajax calls.
+ $.ajaxSetup({
+ dataType: 'json',
+ cache: false,
+ contentType: 'application/json; charset=utf-8'
+ });
+
})(jQuery);
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js
index 646890a042..655a7b1609 100644
--- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js
+++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditView.js
@@ -80,7 +80,7 @@
}),
function(e) {
if (e.success) {
- self.submitSuccess(e.message, e.header);
+ self.submitSuccess(e);
} else {
self.submitFailure(e.message, e.header);
}
@@ -97,7 +97,7 @@
}),
function(e) {
if (e.success) {
- self.submitSuccess(e.message, e.header);
+ self.submitSuccess(e);
} else {
self.submitFailure(e.message, e.header);
}
@@ -105,8 +105,20 @@
}
},
- submitSuccess: function (err, header) {
- top.UmbSpeechBubble.ShowMessage('save', header, err);
+ submitSuccess: function (args) {
+
+ var msg = args.message;
+ var header = args.header;
+ var path = this._opts.treeSyncPath;
+ var pathChanged = false;
+ if (args.path) {
+ if (path != args.path) {
+ pathChanged = true;
+ }
+ path = args.path;
+ }
+
+ top.UmbSpeechBubble.ShowMessage('save', header, msg);
UmbClientMgr.mainTree().setActiveTreeType(this._opts.currentTreeType);
@@ -114,11 +126,19 @@
if (this._opts.editorType == "Template") {
//templates are different because they are ID based, whereas view files are file based without a static id
- UmbClientMgr.mainTree().syncTree(this._opts.treeSyncPath, true);
+
+ if (pathChanged) {
+ UmbClientMgr.mainTree().moveNode(this._opts.templateId, path);
+ }
+ else {
+ UmbClientMgr.mainTree().syncTree(path, true);
+ }
+
+
}
else {
//we need to pass in the newId parameter so it knows which node to resync after retreival from the server
- UmbClientMgr.mainTree().syncTree(this._opts.treeSyncPath, true, null, newFilePath.split("/")[1]);
+ UmbClientMgr.mainTree().syncTree(path, true, null, newFilePath.split("/")[1]);
}
//then we need to update our current tree sync path to represent the new one
diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs
index 39c7baa4e6..7b90da05c1 100644
--- a/src/Umbraco.Web/WebServices/SaveFileController.cs
+++ b/src/Umbraco.Web/WebServices/SaveFileController.cs
@@ -8,7 +8,9 @@ using Umbraco.Web.Macros;
using Umbraco.Web.Mvc;
using umbraco;
using umbraco.cms.businesslogic.macro;
+using System.Collections.Generic;
using Umbraco.Core;
+
using Template = umbraco.cms.businesslogic.template.Template;
namespace Umbraco.Web.WebServices
@@ -90,15 +92,22 @@ namespace Umbraco.Web.WebServices
public JsonResult SaveTemplate(string templateName, string templateAlias, string templateContents, int templateId, int masterTemplateId)
{
Template t;
+ bool pathChanged = false;
try
{
t = new Template(templateId)
{
Text = templateName,
- Alias = templateAlias,
- MasterTemplate = masterTemplateId,
+ Alias = templateAlias,
Design = templateContents
};
+
+ //check if the master page has changed
+ if (t.MasterTemplate != masterTemplateId)
+ {
+ pathChanged = true;
+ t.MasterTemplate = masterTemplateId;
+ }
}
catch (ArgumentException ex)
{
@@ -110,7 +119,17 @@ namespace Umbraco.Web.WebServices
{
t.Save();
- return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"));
+ //ensure the correct path is synced as the parent might have been changed
+ // http://issues.umbraco.org/issue/U4-2300
+ if (pathChanged)
+ {
+ //need to re-look it up
+ t = new Template(templateId);
+ }
+ var syncPath = "-1,init," + t.Path.Replace("-1,", "");
+
+ return Success(ui.Text("speechBubbles", "templateSavedText"), ui.Text("speechBubbles", "templateSavedHeader"),
+ new {path = syncPath});
}
catch (Exception ex)
{
@@ -118,20 +137,21 @@ namespace Umbraco.Web.WebServices
}
}
- ///
- /// Returns a successful message
- ///
- /// The message to display in the speach bubble
- /// The header to display in the speach bubble
- ///
- private JsonResult Success(string message, string header)
- {
- return Json(new
- {
- success = true,
- message = message,
- header = header
- });
+ ///
+ /// Returns a successful message
+ ///
+ /// The message to display in the speach bubble
+ /// The header to display in the speach bubble
+ ///
+ ///
+ private JsonResult Success(string message, string header, object additionalVals = null)
+ {
+ var d = additionalVals == null ? new Dictionary() : additionalVals.ToDictionary
" + ui.Text("closeThisWindow") + "";
feedback.type = uicontrols.Feedback.feedbacktype.success;
From 5640daff321958c70cf7993677d3eaab82170f39 Mon Sep 17 00:00:00 2001
From: Morten Christensen
Date: Fri, 30 Aug 2013 10:50:43 +0200
Subject: [PATCH 11/18] Fixes U4-2752 ContentService.DeleteVersion and
DeleteVersions fail
Signed-off-by: Sebastiaan Janssen
---
.../Repositories/ContentRepository.cs | 24 +++++++++++++++++--
.../Repositories/MediaRepository.cs | 4 ++--
.../Repositories/VersionableRepositoryBase.cs | 8 +++----
.../Services/ContentServiceTests.cs | 16 +++++++++++++
4 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index 870ed2cc00..e0dde68a6c 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -170,11 +170,31 @@ namespace Umbraco.Core.Persistence.Repositories
return content;
}
+ public override void DeleteVersion(Guid versionId)
+ {
+ var sql = new Sql()
+ .Select("*")
+ .From()
+ .InnerJoin().On(left => left.VersionId, right => right.VersionId)
+ .Where(x => x.VersionId == versionId)
+ .Where(x => x.Newest == true);
+ var dto = Database.Fetch(sql).FirstOrDefault();
+
+ if(dto == null) return;
+
+ using (var transaction = Database.GetTransaction())
+ {
+ PerformDeleteVersion(dto.NodeId, versionId);
+
+ transaction.Complete();
+ }
+ }
+
protected override void PerformDeleteVersion(int id, Guid versionId)
{
Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
- Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
- Database.Delete("WHERE nodeId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
+ Database.Delete("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
+ Database.Delete("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
}
diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
index e27fac1ba3..8292fc8977 100644
--- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
@@ -176,8 +176,8 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PerformDeleteVersion(int id, Guid versionId)
{
Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
- Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
- Database.Delete("WHERE nodeId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
+ Database.Delete("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId });
+ Database.Delete("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId });
}
#endregion
diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs
index 0ed84582fa..9b9160b66a 100644
--- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs
@@ -43,8 +43,8 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual void DeleteVersion(Guid versionId)
{
- var dto = Database.FirstOrDefault("WHERE versionId = @VersionId AND newest = @Newest", new { VersionId = versionId, Newest = false });
- Mandate.That(dto != null);
+ var dto = Database.FirstOrDefault("WHERE versionId = @VersionId", new { VersionId = versionId });
+ if(dto == null) return;
using (var transaction = Database.GetTransaction())
{
@@ -56,8 +56,8 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual void DeleteVersions(int id, DateTime versionDate)
{
- var list = Database.Fetch("WHERE nodeId = @Id AND VersionDate < @VersionDate", new { Id = id, VersionDate = versionDate });
- Mandate.That(list.Any());
+ var list = Database.Fetch("WHERE ContentId = @Id AND VersionDate < @VersionDate", new { Id = id, VersionDate = versionDate });
+ if (list.Any() == false) return;
using (var transaction = Database.GetTransaction())
{
diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs
index 522f608272..a8d3f6d30c 100644
--- a/src/Umbraco.Tests/Services/ContentServiceTests.cs
+++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs
@@ -861,6 +861,22 @@ namespace Umbraco.Tests.Services
Assert.That(sut.GetValue("imgCropper"), Is.Empty);
}
+ [Test]
+ public void Can_Delete_Previous_Versions_Not_Latest()
+ {
+ // Arrange
+ var contentService = ServiceContext.ContentService;
+ var content = contentService.GetById(1049);
+ var version = content.Version;
+
+ // Act
+ contentService.DeleteVersion(1049, version, true, 0);
+ var sut = contentService.GetById(1049);
+
+ // Assert
+ Assert.That(sut.Version, Is.EqualTo(version));
+ }
+
private IEnumerable CreateContentHierarchy()
{
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
From 7765acb130eafc8b0bc01afdc2c6aeeedf5b7dde Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Sun, 1 Sep 2013 05:22:51 -0700
Subject: [PATCH 12/18] Merge pull request #124 from AndyButland/wip-u4-2759
U4-2759 - member authorise attribute was not restricting for group
---
src/Umbraco.Web/Security/WebSecurity.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs
index f45ff9c30e..a7a57c3c32 100644
--- a/src/Umbraco.Web/Security/WebSecurity.cs
+++ b/src/Umbraco.Web/Security/WebSecurity.cs
@@ -70,15 +70,15 @@ namespace Umbraco.Web.Security
var allowGroupsList = allowGroups as IList ?? allowGroups.ToList();
if (allowAction && allowGroupsList.Any(allowGroup => allowGroup != string.Empty))
{
- // Allow only if member's type is in list
+ // Allow only if member is assigned to a group in the list
var groups = Roles.GetRolesForUser(member.LoginName);
- allowAction = groups.Select(s => s.ToLowerInvariant()).Intersect(groups.Select(myGroup => myGroup.ToLowerInvariant())).Any();
+ allowAction = allowGroupsList.Select(s => s.ToLowerInvariant()).Intersect(groups.Select(myGroup => myGroup.ToLowerInvariant())).Any();
}
// If specific members defined, check member is of one of those
if (allowAction && allowMembers.Any())
{
- // Allow only if member's type is in list
+ // Allow only if member's Id is in the list
allowAction = allowMembers.Contains(member.Id);
}
}
From 5478de911b88e4908c6bc4860947ff3d3f552585 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Sun, 1 Sep 2013 05:34:18 -0700
Subject: [PATCH 13/18] Merge pull request #115 from stocksr/6.2.0
U4-516 - Fix DatePicker with time default value
---
.../umbraco_client/DateTimePicker/timepicker.js | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/Umbraco.Web.UI/umbraco_client/DateTimePicker/timepicker.js b/src/Umbraco.Web.UI/umbraco_client/DateTimePicker/timepicker.js
index af27a79d43..f5034b4707 100644
--- a/src/Umbraco.Web.UI/umbraco_client/DateTimePicker/timepicker.js
+++ b/src/Umbraco.Web.UI/umbraco_client/DateTimePicker/timepicker.js
@@ -62,9 +62,19 @@ $.datepicker._connectDatepicker = function(target, inst) {
*/
$.datepicker._showDatepickerOverride = $.datepicker._showDatepicker;
$.datepicker._showDatepicker = function (input) {
+ // keep the current value
+ var originalval = input.value;
+
+ // Keep the first 10 chars for now yyyy-mm-dd - this removes the time part which was breaking the standardDatePicker parsing code
+ input.value = originalval.length>10 ? originalval.substring(0, 10) : originalval;
+
+
// Call the original method which will show the datepicker
$.datepicker._showDatepickerOverride(input);
+ // Put it back
+ input.value = originalval;
+
input = input.target || input;
// find from button/image trigger
From 2111a5e31e906630998c827cdd7d4238a288be9a Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Sun, 1 Sep 2013 17:21:19 +0200
Subject: [PATCH 14/18] Fix MySQL install failing on UmbracoServer table
---
.../DatabaseModelDefinitions/DefinitionFactory.cs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs
index f987e69b3d..9b08279716 100644
--- a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs
+++ b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DefinitionFactory.cs
@@ -3,6 +3,7 @@ using System.Data;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Persistence.DatabaseAnnotations;
+using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
@@ -107,6 +108,12 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
var constraintAttribute = propertyInfo.FirstAttribute();
if (constraintAttribute != null)
{
+ //Special case for MySQL as it can't have multiple default DateTime values, which
+ //is what the umbracoServer table definition is trying to create
+ if (SqlSyntaxContext.SqlSyntaxProvider is MySqlSyntaxProvider && definition.TableName == "umbracoServer" &&
+ definition.TableName.ToLowerInvariant() == "lastNotifiedDate".ToLowerInvariant())
+ return definition;
+
definition.ConstraintName = constraintAttribute.Name ?? string.Empty;
definition.DefaultValue = constraintAttribute.Default ?? string.Empty;
}
From da1c33a0349503caa460c3d5bbc3b25114523202 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Mon, 2 Sep 2013 12:57:56 +1000
Subject: [PATCH 15/18] Fixes unit test
---
.gitignore | 3 +++
src/Umbraco.Tests/Models/DataValueSetterTests.cs | 2 ++
2 files changed, 5 insertions(+)
diff --git a/.gitignore b/.gitignore
index 9496a86e70..da24566589 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,3 +81,6 @@ build/_BuildOutput/
tools/NDepend/
src/*.vspx
src/*.psess
+NDependOut/*
+QueryResult.htm
+*.ndproj
diff --git a/src/Umbraco.Tests/Models/DataValueSetterTests.cs b/src/Umbraco.Tests/Models/DataValueSetterTests.cs
index db59217166..25b0f53883 100644
--- a/src/Umbraco.Tests/Models/DataValueSetterTests.cs
+++ b/src/Umbraco.Tests/Models/DataValueSetterTests.cs
@@ -66,6 +66,8 @@ namespace Umbraco.Tests.Models
var dataTypeId = Guid.NewGuid();
var dataTypeData = MockRepository.GenerateMock();
+ //needs to have a value for SetValue to be called
+ dataTypeData.Stub(data => data.Value).Return(string.Empty);
dataTypeData
.Stub(data => data.ToXMl(Arg.Is.Anything))
.Return(null) // you have to call Return() even though we're about to override it
From 5989d19f7f25c06393e7fa81a2b0417479ab6fe5 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Mon, 2 Sep 2013 13:27:48 +1000
Subject: [PATCH 16/18] Re-fixes the issue with using IDataValueSetter.SetValue
on the DefaultData implementation and ensures that when there is a null value
that it reverts to an empty string since this was what the default value was
in the Value getter of DefaultData when there was no value. Have added a
couple unit tests to support.
---
src/Umbraco.Core/Models/PropertyExtensions.cs | 2 +-
src/Umbraco.Tests/Models/DataValueSetterTests.cs | 16 ++++++++++++++--
.../businesslogic/datatype/DefaultData.cs | 11 +++++++++++
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs
index 2ef594c8c2..ae01532c87 100644
--- a/src/Umbraco.Core/Models/PropertyExtensions.cs
+++ b/src/Umbraco.Core/Models/PropertyExtensions.cs
@@ -43,7 +43,7 @@ namespace Umbraco.Core.Models
//This seems to fail during testing
//SD: With the new null checks below, this shouldn't fail anymore.
var dt = property.PropertyType.DataType(property.Id, dataTypeService);
- if (dt != null && dt.Data != null && dt.Data.Value != null)
+ if (dt != null && dt.Data != null)
{
//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.
diff --git a/src/Umbraco.Tests/Models/DataValueSetterTests.cs b/src/Umbraco.Tests/Models/DataValueSetterTests.cs
index 25b0f53883..891c53dd0d 100644
--- a/src/Umbraco.Tests/Models/DataValueSetterTests.cs
+++ b/src/Umbraco.Tests/Models/DataValueSetterTests.cs
@@ -66,8 +66,7 @@ namespace Umbraco.Tests.Models
var dataTypeId = Guid.NewGuid();
var dataTypeData = MockRepository.GenerateMock();
- //needs to have a value for SetValue to be called
- dataTypeData.Stub(data => data.Value).Return(string.Empty);
+
dataTypeData
.Stub(data => data.ToXMl(Arg.Is.Anything))
.Return(null) // you have to call Return() even though we're about to override it
@@ -100,5 +99,18 @@ namespace Umbraco.Tests.Models
((IDataValueSetter)dataTypeData).AssertWasCalled(setter => setter.SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString()));
}
+ [TestCase(DataTypeDatabaseType.Nvarchar)]
+ [TestCase(DataTypeDatabaseType.Date)]
+ [TestCase(DataTypeDatabaseType.Integer)]
+ [TestCase(DataTypeDatabaseType.Ntext)]
+ public void DefaultData_SetValue_Ensures_Empty_String_When_Null_Value_Any_Data_Type(DataTypeDatabaseType type)
+ {
+ var defaultData = new DefaultData(MockRepository.GenerateMock());
+
+ ((IDataValueSetter)defaultData).SetValue(null, type.ToString());
+
+ Assert.AreEqual(string.Empty, defaultData.Value);
+ }
+
}
}
\ No newline at end of file
diff --git a/src/umbraco.cms/businesslogic/datatype/DefaultData.cs b/src/umbraco.cms/businesslogic/datatype/DefaultData.cs
index a974fda7c2..471fcc9479 100644
--- a/src/umbraco.cms/businesslogic/datatype/DefaultData.cs
+++ b/src/umbraco.cms/businesslogic/datatype/DefaultData.cs
@@ -65,6 +65,17 @@ namespace umbraco.cms.businesslogic.datatype
///
void IDataValueSetter.SetValue(object val, string strDbType)
{
+ //We need to ensure that val is not a null value, if it is then we'll convert this to an empty string.
+ //The reason for this is because by default the DefaultData.Value property returns an empty string when
+ // there is no value, this is based on the PropertyDataDto.GetValue return value which defaults to an
+ // empty string (which is called from this class's method LoadValueFromDatabase).
+ //Some legacy implementations of DefaultData are expecting an empty string when there is
+ // no value so we need to keep this consistent.
+ if (val == null)
+ {
+ val = string.Empty;
+ }
+
_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.
From 7c28e1aeba4f34c7aff2a600108f258990815160 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Mon, 2 Sep 2013 10:56:42 +0200
Subject: [PATCH 17/18] Fixed U4-2763 Content rollback generates duplicates
---
.../Repositories/ContentRepository.cs | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index e0dde68a6c..e34fed0c56 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -360,19 +360,19 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
+ //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);
+ }
+
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);
From 173ac65eb57d9305decadaa80e72054a8e1e6b49 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Mon, 2 Sep 2013 11:41:13 +0200
Subject: [PATCH 18/18] Remove misleading comment as this has been moved out of
the if statement
---
src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index e34fed0c56..f290b5b54a 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -361,7 +361,6 @@ namespace Umbraco.Core.Persistence.Repositories
}
//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)
{