* First Go at the single block property editor based on blocklistpropertyeditor * Add simalar tests to the blocklist editor Also check whether either block of configured blocks can be picked and used from a data perspective * WIP singleblock Valiation tests * Finished first full pass off SingleBlock validation testing * Typos, Future test function * Restore accidently removed file * Introduce propertyValueConverter * Comment updates * Add singleBlock renderer * Textual improvements Comment improvements, remove licensing in file * Update DataEditorCount by 1 as we introduced a new one * Align test naming * Add ignored singleblock default renderer * Enable SingleBlock Property Indexing * Enable Partial value merging * Fix indentation --------- Co-authored-by: kjac <kja@umbraco.dk>
188 lines
7.2 KiB
C#
188 lines
7.2 KiB
C#
using Umbraco.Cms.Core.Models;
|
|
using Umbraco.Cms.Core.Models.ContentEditing;
|
|
using Umbraco.Extensions;
|
|
|
|
namespace Umbraco.Cms.Core.Services;
|
|
|
|
// Disclaimer: Based on code generated by Claude code.
|
|
// Most likely not complete, but the logic looks sound.
|
|
public interface IContentEditingModelFactory
|
|
{
|
|
Task<ContentUpdateModel> CreateFromAsync(IContent content);
|
|
}
|
|
|
|
public class ContentEditingModelFactory : IContentEditingModelFactory
|
|
{
|
|
private readonly ITemplateService _templateService;
|
|
|
|
public ContentEditingModelFactory(ITemplateService templateService)
|
|
{
|
|
_templateService = templateService;
|
|
}
|
|
|
|
public async Task<ContentUpdateModel> CreateFromAsync(IContent content)
|
|
{
|
|
{
|
|
var templateKey = content.TemplateId.HasValue
|
|
? (await _templateService.GetAsync(content.TemplateId.Value))?.Key
|
|
: null;
|
|
var model = new ContentUpdateModel { TemplateKey = templateKey };
|
|
var properties = new List<PropertyValueModel>();
|
|
var variants = new List<VariantModel>();
|
|
|
|
MapProperties(content, properties);
|
|
|
|
MapNames(content, properties, variants);
|
|
|
|
model.Properties = properties;
|
|
model.Variants = variants;
|
|
return model;
|
|
}
|
|
}
|
|
|
|
private static void MapNames(IContent content, List<PropertyValueModel> properties, List<VariantModel> variants)
|
|
{
|
|
// Handle variants (content names per culture/segment)
|
|
var contentVariesByCulture = content.ContentType.VariesByCulture();
|
|
var contentVariesBySegment = content.ContentType.VariesBySegment();
|
|
if (contentVariesByCulture || contentVariesBySegment)
|
|
{
|
|
// Get all unique culture/segment combinations from CultureInfos
|
|
var cultureSegmentCombinations = new HashSet<(string? culture, string? segment)>();
|
|
|
|
// Add invariant combination
|
|
cultureSegmentCombinations.Add((null, null));
|
|
if (contentVariesByCulture)
|
|
{
|
|
// Add cultures
|
|
foreach (var culture in content.AvailableCultures)
|
|
{
|
|
cultureSegmentCombinations.Add((culture, null));
|
|
}
|
|
}
|
|
|
|
// For segment support, we need to extract segments from property values
|
|
// since content doesn't have "AvailableSegments" like cultures
|
|
if (contentVariesBySegment)
|
|
{
|
|
var segmentsFromProperties = properties
|
|
.Where(p => !string.IsNullOrEmpty(p.Segment))
|
|
.Select(p => p.Segment)
|
|
.Distinct()
|
|
.ToList();
|
|
foreach (var segment in segmentsFromProperties)
|
|
{
|
|
cultureSegmentCombinations.Add((null, segment));
|
|
// If content also varies by culture, add culture+segment combinations
|
|
if (contentVariesByCulture)
|
|
{
|
|
foreach (var culture in content.AvailableCultures)
|
|
{
|
|
cultureSegmentCombinations.Add((culture, segment));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create variants for each combination
|
|
foreach (var (culture, segment) in cultureSegmentCombinations)
|
|
{
|
|
string? variantName;
|
|
if (culture == null && segment == null)
|
|
{
|
|
// Invariant
|
|
variantName = content.Name;
|
|
}
|
|
else if (culture != null && segment == null)
|
|
{
|
|
// Culture-specific
|
|
variantName = content.GetCultureName(culture);
|
|
}
|
|
else
|
|
{
|
|
// For segment-specific or culture+segment combinations,
|
|
// we'll use the invariant or culture name as segments don't have separate names
|
|
variantName = culture != null ? content.GetCultureName(culture) : content.Name;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(variantName))
|
|
{
|
|
variants.Add(new VariantModel { Culture = culture, Segment = segment, Name = variantName });
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For invariant content, add single variant
|
|
variants.Add(new VariantModel { Culture = null, Segment = null, Name = content.Name ?? string.Empty });
|
|
}
|
|
}
|
|
|
|
private static void MapProperties(IContent content, List<PropertyValueModel> properties)
|
|
{
|
|
// Handle properties
|
|
foreach (var property in content.Properties)
|
|
{
|
|
var propertyVariesByCulture = property.PropertyType.VariesByCulture();
|
|
var propertyVariesBySegment = property.PropertyType.VariesBySegment();
|
|
|
|
// Get all property values from the property's Values collection
|
|
foreach (var propertyValue in property.Values)
|
|
{
|
|
if (propertyValue.EditedValue != null)
|
|
{
|
|
properties.Add(new PropertyValueModel
|
|
{
|
|
Alias = property.Alias,
|
|
Value = propertyValue.EditedValue,
|
|
Culture = propertyVariesByCulture ? propertyValue.Culture : null,
|
|
Segment = propertyVariesBySegment ? propertyValue.Segment : null,
|
|
});
|
|
}
|
|
}
|
|
|
|
// Fallback: if no values found in the Values collection, try the traditional approach
|
|
if (!property.Values.Any())
|
|
{
|
|
if (propertyVariesByCulture && content.AvailableCultures.Any())
|
|
{
|
|
// Handle culture variants
|
|
foreach (var culture in content.AvailableCultures)
|
|
{
|
|
var cultureValue = property.GetValue(culture);
|
|
if (cultureValue != null)
|
|
{
|
|
properties.Add(new PropertyValueModel
|
|
{
|
|
Alias = property.Alias, Value = cultureValue, Culture = culture, Segment = null,
|
|
});
|
|
}
|
|
}
|
|
|
|
// Also add the invariant value if it exists
|
|
var invariantValue = property.GetValue();
|
|
if (invariantValue != null)
|
|
{
|
|
properties.Add(new PropertyValueModel
|
|
{
|
|
Alias = property.Alias, Value = invariantValue, Culture = null, Segment = null,
|
|
});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Handle invariant properties
|
|
var value = property.GetValue();
|
|
if (value != null)
|
|
{
|
|
properties.Add(new PropertyValueModel
|
|
{
|
|
Alias = property.Alias, Value = value, Culture = null, Segment = null,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|