Skip to content

Commit 3ca5443

Browse files
Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0
2 parents f6d56f5 + 6d3e8e1 commit 3ca5443

File tree

11 files changed

+158
-25
lines changed

11 files changed

+158
-25
lines changed

src/Umbraco.Tests/PublishedContent/DynamicPublishedContentTests.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,16 @@ public void Returns_DynamicDocument_Object_After_Casting()
7272
Assert.IsTrue(ddoc.HasProperty(Constants.Conventions.Content.UrlAlias));
7373
}
7474

75-
/// <summary>
75+
[Test]
76+
public void U4_4559()
77+
{
78+
var doc = GetDynamicNode(1174);
79+
var result = doc.AncestorOrSelf(1);
80+
Assert.IsNotNull(result);
81+
Assert.AreEqual(1046, result.Id);
82+
}
83+
84+
/// <summary>
7685
/// Test class to mimic UmbracoHelper when returning docs
7786
/// </summary>
7887
public class TestHelper

src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,15 @@ public void Ancestor_Or_Self()
508508
Assert.AreEqual(1173, result.Id);
509509
}
510510

511+
[Test]
512+
public void U4_4559()
513+
{
514+
var doc = GetNode(1174);
515+
var result = doc.AncestorOrSelf(1);
516+
Assert.IsNotNull(result);
517+
Assert.AreEqual(1046, result.Id);
518+
}
519+
511520
[Test]
512521
public void Ancestors_Or_Self()
513522
{

src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
angular.module("umbraco.install").controller("Umbraco.Install.UserController", function($scope, installerService) {
22

33
$scope.passwordPattern = /.*/;
4+
$scope.installer.current.model.subscribeToNewsLetter = true;
5+
46
if ($scope.installer.current.model.minNonAlphaNumericLength > 0) {
57
var exp = "";
68
for (var i = 0; i < $scope.installer.current.model.minNonAlphaNumericLength; i++) {

src/Umbraco.Web.UI.Client/src/installer/steps/user.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,22 @@ <h1>Install Umbraco 7</h1>
3333
required
3434
ng-model="installer.current.model.password" />
3535
<small class="inline-help">At least {{installer.current.model.minCharLength}} characters long</small>
36+
3637
<small ng-if="installer.current.model.minNonAlphaNumericLength > 0" class="inline-help">
3738
At least {{installer.current.model.minNonAlphaNumericLength}} symbol{{installer.current.model.minNonAlphaNumericLength > 1 ? 's' : ''}}
3839
</small>
3940
</div>
4041
</div>
4142

43+
44+
<div class="control-group">
45+
<div class="controls">
46+
<label class="checkbox" for="subscribeToNewsLetter">
47+
<input type="checkbox" name="subscribeToNewsLetter"
48+
ng-model="installer.current.model.subscribeToNewsLetter" /> Subscribe to our newsletter</label>
49+
</div>
50+
</div>
51+
4252
<div class="control-group" ng-class="{disabled:myForm.$invalid}">
4353
<div class="controls">
4454

src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,53 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownController
99

1010
//map the user config
1111
angular.extend(config, $scope.model.config);
12+
1213
//map back to the model
1314
$scope.model.config = config;
1415

15-
if (angular.isArray($scope.model.config.items)) {
16-
17-
//ensure the items are sorted by the provided sort order
18-
$scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
16+
function convertArrayToDictionaryArray(model){
17+
//now we need to format the items in the dictionary because we always want to have an array
18+
var newItems = [];
19+
for (var i = 0; i < model.length; i++) {
20+
newItems.push({ id: model[i], sortOrder: 0, value: model[i] });
21+
}
1922

23+
return newItems;
2024
}
21-
else if (angular.isObject($scope.model.config.items)) {
2225

26+
27+
function convertObjectToDictionaryArray(model){
2328
//now we need to format the items in the dictionary because we always want to have an array
2429
var newItems = [];
2530
var vals = _.values($scope.model.config.items);
2631
var keys = _.keys($scope.model.config.items);
32+
2733
for (var i = 0; i < vals.length; i++) {
2834
var label = vals[i].value ? vals[i].value : vals[i];
2935
newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label });
3036
}
3137

32-
//ensure the items are sorted by the provided sort order
33-
newItems.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
38+
return newItems;
39+
}
3440

35-
//re-assign
36-
$scope.model.config.items = newItems;
41+
if (angular.isArray($scope.model.config.items)) {
42+
//PP: I dont think this will happen, but we have tests that expect it to happen..
43+
//if array is simple values, convert to array of objects
44+
if(!angular.isObject($scope.model.config.items[0])){
45+
$scope.model.config.items = convertArrayToDictionaryArray($scope.model.config.items);
46+
}
47+
}
48+
else if (angular.isObject($scope.model.config.items)) {
49+
$scope.model.config.items = convertObjectToDictionaryArray($scope.model.config.items);
3750
}
3851
else {
3952
throw "The items property must be either an array or a dictionary";
4053
}
4154

55+
56+
//sort the values
57+
$scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
58+
4259
//now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set
4360
// to "" gets selected by default
4461
if ($scope.model.value === null || $scope.model.value === undefined) {

src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/dropdown-controller.spec.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('Drop down controller tests', function () {
2323
expect(scope.model.config.items).toBeDefined();
2424
expect(scope.model.config.multiple).toBeDefined();
2525
});
26-
26+
2727
it("should convert simple array to dictionary", function () {
2828

2929
scope.model = {
@@ -37,12 +37,13 @@ describe('Drop down controller tests', function () {
3737
$routeParams: routeParams
3838
});
3939

40-
expect(scope.model.config.items["value0"]).toBe("value0");
41-
expect(scope.model.config.items["value1"]).toBe("value1");
42-
expect(scope.model.config.items["value2"]).toBe("value2");
43-
40+
//this should be the expected format based on the changes made to the sortable prevalues
41+
expect(scope.model.config.items[0].value).toBe("value0");
42+
expect(scope.model.config.items[1].value).toBe("value1");
43+
expect(scope.model.config.items[2].value).toBe("value2");
4444
});
4545

46+
4647
it("should allow an existing valid dictionary", function () {
4748

4849
scope.model = {

src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Specialized;
34
using System.Configuration;
45
using System.Web.Security;
56
using Umbraco.Core;
@@ -69,7 +70,19 @@ public override InstallSetupResult Execute(UserModel user)
6970
admin.Username = user.Email.Trim();
7071

7172
_applicationContext.Services.UserService.Save(admin);
72-
73+
74+
75+
if (user.SubscribeToNewsLetter)
76+
{
77+
try
78+
{
79+
var client = new System.Net.WebClient();
80+
var values = new NameValueCollection { { "name", admin.Name }, { "email", admin.Email} };
81+
client.UploadValues("http://umbraco.org/base/Ecom/SubmitEmail/installer.aspx", values);
82+
}
83+
catch { /* fail in silence */ }
84+
}
85+
7386
return null;
7487
}
7588

src/Umbraco.Web/Install/Models/UserModel.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ public class UserModel
1313

1414
[DataMember(Name = "password")]
1515
public string Password { get; set; }
16+
17+
[DataMember(Name = "subscribeToNewsLetter")]
18+
public bool SubscribeToNewsLetter { get; set; }
1619
}
1720
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Umbraco.Core;
7+
using Umbraco.Core.Models;
8+
using Umbraco.Core.Models.PublishedContent;
9+
using Umbraco.Core.PropertyEditors;
10+
using Umbraco.Core.Services;
11+
12+
namespace Umbraco.Web.Models
13+
{
14+
public static class PublishedProperty
15+
{
16+
/// <summary>
17+
/// Maps a collection of Property to a collection of IPublishedProperty for a specified collection of PublishedPropertyType.
18+
/// </summary>
19+
/// <param name="propertyTypes">The published property types.</param>
20+
/// <param name="properties">The properties.</param>
21+
/// <param name="map">A mapping function.</param>
22+
/// <returns>A collection of IPublishedProperty corresponding to the collection of PublishedPropertyType
23+
/// and taking values from the collection of Property.</returns>
24+
/// <remarks>Ensures that all conversions took place correctly.</remarks>
25+
internal static IEnumerable<IPublishedProperty> MapProperties(
26+
IEnumerable<PublishedPropertyType> propertyTypes, IEnumerable<Property> properties,
27+
Func<PublishedPropertyType, Property, object, IPublishedProperty> map)
28+
{
29+
var peResolver = PropertyEditorResolver.Current;
30+
var dtService = ApplicationContext.Current.Services.DataTypeService;
31+
return MapProperties(propertyTypes, properties, peResolver, dtService, map);
32+
}
33+
34+
/// <summary>
35+
/// Maps a collection of Property to a collection of IPublishedProperty for a specified collection of PublishedPropertyType.
36+
/// </summary>
37+
/// <param name="propertyTypes">The published property types.</param>
38+
/// <param name="properties">The properties.</param>
39+
/// <param name="map">A mapping function.</param>
40+
/// <param name="propertyEditorResolver">A PropertyEditorResolver instance.</param>
41+
/// <param name="dataTypeService">An IDataTypeService instance.</param>
42+
/// <returns>A collection of IPublishedProperty corresponding to the collection of PublishedPropertyType
43+
/// and taking values from the collection of Property.</returns>
44+
/// <remarks>Ensures that all conversions took place correctly.</remarks>
45+
internal static IEnumerable<IPublishedProperty> MapProperties(
46+
IEnumerable<PublishedPropertyType> propertyTypes, IEnumerable<Property> properties,
47+
PropertyEditorResolver propertyEditorResolver, IDataTypeService dataTypeService,
48+
Func<PublishedPropertyType, Property, object, IPublishedProperty> map)
49+
{
50+
return propertyTypes
51+
.Select(x =>
52+
{
53+
var p = properties.SingleOrDefault(xx => xx.Alias == x.PropertyTypeAlias);
54+
var v = p == null || p.Value == null ? null : p.Value;
55+
if (v != null)
56+
{
57+
var e = propertyEditorResolver.GetByAlias(x.PropertyEditorAlias);
58+
if (e != null)
59+
v = e.ValueEditor.ConvertDbToString(p, p.PropertyType, dataTypeService);
60+
}
61+
// fixme - means that the IPropertyValueConverter will always get a string
62+
// fixme and never an int or DateTime that's in the DB unless the value editor has
63+
// fixme a way to say it's OK to use what's in the DB?
64+
65+
return map(x, p, v);
66+
});
67+
}
68+
}
69+
}

src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using Umbraco.Core;
77
using Umbraco.Core.Models;
88
using Umbraco.Core.Models.PublishedContent;
9+
using Umbraco.Core.PropertyEditors;
10+
using Umbraco.Core.Services;
911
using Umbraco.Web.Models;
1012

1113
namespace Umbraco.Web.PublishedCache
@@ -18,7 +20,7 @@ internal class MemberPublishedContent : PublishedContentBase
1820

1921
private readonly IMember _member;
2022
private readonly MembershipUser _membershipUser;
21-
private readonly List<IPublishedProperty> _properties;
23+
private readonly IPublishedProperty[] _properties;
2224
private readonly PublishedContentType _publishedMemberType;
2325

2426
public MemberPublishedContent(IMember member, MembershipUser membershipUser)
@@ -28,21 +30,18 @@ public MemberPublishedContent(IMember member, MembershipUser membershipUser)
2830

2931
_member = member;
3032
_membershipUser = membershipUser;
31-
_properties = new List<IPublishedProperty>();
3233
_publishedMemberType = PublishedContentType.Get(PublishedItemType.Member, _member.ContentTypeAlias);
3334
if (_publishedMemberType == null)
3435
{
3536
throw new InvalidOperationException("Could not get member type with alias " + _member.ContentTypeAlias);
3637
}
37-
foreach (var propType in _publishedMemberType.PropertyTypes)
38-
{
39-
var val = _member.Properties.Any(x => x.Alias == propType.PropertyTypeAlias) == false
40-
? string.Empty
41-
: _member.Properties[propType.PropertyTypeAlias].Value;
42-
_properties.Add(new RawValueProperty(propType, val ?? string.Empty));
43-
}
38+
39+
_properties = PublishedProperty.MapProperties(_publishedMemberType.PropertyTypes, _member.Properties,
40+
(t, p, v) => new RawValueProperty(t, v ?? string.Empty))
41+
.ToArray();
4442
}
4543

44+
4645
#region Membership provider member properties
4746
public string Email
4847
{

src/Umbraco.Web/Umbraco.Web.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@
352352
<Compile Include="Models\ImageCropData.cs" />
353353
<Compile Include="Models\IRenderModel.cs" />
354354
<Compile Include="Models\PostRedirectModel.cs" />
355+
<Compile Include="Models\PublishedProperty.cs" />
355356
<Compile Include="Mvc\RedirectToUmbracoUrlResult.cs" />
356357
<Compile Include="PublishedCache\MemberPublishedContent.cs" />
357358
<Compile Include="PublishedCache\RawValueProperty.cs" />

0 commit comments

Comments
 (0)