diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs
index c5c22484ad..2b70a63035 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyBasic.cs
@@ -53,11 +53,21 @@ namespace Umbraco.Web.Models.ContentEditing
[ReadOnly(true)]
public string Culture { get; set; }
+ ///
+ /// The segment of the property
+ ///
+ ///
+ /// The segment value of a property can always be null but can only have a non-null value
+ /// when the property can be varied by segment.
+ ///
+ [DataMember(Name = "segment")]
+ [ReadOnly(true)]
+ public string Segment { get; set; }
+
///
/// Used internally during model mapping
///
[IgnoreDataMember]
internal IDataEditor PropertyEditor { get; set; }
-
}
}
diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs
index 36c1b360b2..aacafd2f2a 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicMapper.cs
@@ -70,8 +70,14 @@ namespace Umbraco.Web.Models.Mapping
dest.Culture = culture;
+ var segment = context.GetSegment();
+
+ // The current segment can always be null, even if the propertyType *can* be varied by segment
+ // so the nullcheck like with culture is not performed here.
+ dest.Segment = segment;
+
// if no 'IncludeProperties' were specified or this property is set to be included - we will map the value and return.
- dest.Value = editor.GetValueEditor().ToEditor(property, DataTypeService, culture);
+ dest.Value = editor.GetValueEditor().ToEditor(property, DataTypeService, culture, segment);
}
}
}
diff --git a/src/Umbraco.Web/Models/Mapping/ContentVariantMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentVariantMapper.cs
index c279ae2c70..848eaa0594 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentVariantMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentVariantMapper.cs
@@ -21,27 +21,35 @@ namespace Umbraco.Web.Models.Mapping
public IEnumerable Map(IContent source, MapperContext context)
{
- var result = new List();
- if (!source.ContentType.VariesByCulture())
+ var variants = new List();
+
+ var variesByCulture = source.ContentType.VariesByCulture();
+ var variesBySegment = source.ContentType.VariesBySegment();
+
+ if (!variesByCulture && !variesBySegment)
{
//this is invariant so just map the IContent instance to ContentVariationDisplay
- result.Add(context.Map(source));
+ variants.Add(context.Map(source));
+ return variants;
}
- else
+
+ if (variesByCulture && !variesBySegment)
{
+ // Culture only
+
var allLanguages = _localizationService.GetAllLanguages().OrderBy(x => x.Id).ToList();
if (allLanguages.Count == 0) return Enumerable.Empty(); //this should never happen
var langs = context.MapEnumerable(allLanguages).ToList();
//create a variant for each language, then we'll populate the values
- var variants = langs.Select(x =>
+ variants.AddRange(langs.Select(x =>
{
//We need to set the culture in the mapping context since this is needed to ensure that the correct property values
//are resolved during the mapping
context.SetCulture(x.IsoCode);
return context.Map(source);
- }).ToList();
+ }));
for (int i = 0; i < langs.Count; i++)
{
@@ -63,10 +71,49 @@ namespace Umbraco.Web.Models.Mapping
//Insert the default language as the first item
variants.Insert(0, defaultLang);
-
- return variants;
}
- return result;
+ else if (variesBySegment && !variesByCulture)
+ {
+ // Segment only
+ throw new NotSupportedException("ContentVariantMapper not implemented for segment only!");
+ }
+ else
+ {
+ // Culture and segment
+
+ var allLanguages = _localizationService.GetAllLanguages().OrderBy(x => x.Id).ToList();
+ if (allLanguages.Count == 0) return Enumerable.Empty(); //this should never happen
+
+ var langs = context.MapEnumerable(allLanguages).ToList();
+
+ // All segments, including the unsegmented (= NULL) segment.
+ // TODO: The NULl segment might have to be changed to be empty string?
+ var segments = source.Properties
+ .SelectMany(p => p.Values.Select(v => v.Segment))
+ .Distinct();
+
+ // Add all variants
+ foreach (var language in langs)
+ {
+ foreach (var segment in segments)
+ {
+ context.SetCulture(language.IsoCode);
+ context.SetSegment(segment);
+
+ var variantDisplay = context.Map(source);
+
+ variantDisplay.Language = language;
+ variantDisplay.Segment = segment;
+ variantDisplay.Name = source.GetCultureName(language.IsoCode);
+
+ variants.Add(variantDisplay);
+ }
+ }
+
+ // TODO: Sorting
+ }
+
+ return variants;
}
}
}
diff --git a/src/Umbraco.Web/Models/Mapping/MapperContextExtensions.cs b/src/Umbraco.Web/Models/Mapping/MapperContextExtensions.cs
index 1538f1a987..20a387c679 100644
--- a/src/Umbraco.Web/Models/Mapping/MapperContextExtensions.cs
+++ b/src/Umbraco.Web/Models/Mapping/MapperContextExtensions.cs
@@ -8,6 +8,7 @@ namespace Umbraco.Web.Models.Mapping
internal static class MapperContextExtensions
{
private const string CultureKey = "Map.Culture";
+ private const string SegmentKey = "Map.Segment";
private const string IncludedPropertiesKey = "Map.IncludedProperties";
///
@@ -18,6 +19,14 @@ namespace Umbraco.Web.Models.Mapping
return context.HasItems && context.Items.TryGetValue(CultureKey, out var obj) && obj is string s ? s : null;
}
+ ///
+ /// Gets the context segment.
+ ///
+ public static string GetSegment(this MapperContext context)
+ {
+ return context.HasItems && context.Items.TryGetValue(SegmentKey, out var obj) && obj is string s ? s : null;
+ }
+
///
/// Sets a context culture.
///
@@ -26,6 +35,14 @@ namespace Umbraco.Web.Models.Mapping
context.Items[CultureKey] = culture;
}
+ ///
+ /// Sets a context segment.
+ ///
+ public static void SetSegment(this MapperContext context, string segment)
+ {
+ context.Items[SegmentKey] = segment;
+ }
+
///
/// Get included properties.
///
@@ -42,4 +59,4 @@ namespace Umbraco.Web.Models.Mapping
context.Items[IncludedPropertiesKey] = properties;
}
}
-}
\ No newline at end of file
+}