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 CreateFromAsync(IContent content); } public class ContentEditingModelFactory : IContentEditingModelFactory { private readonly ITemplateService _templateService; public ContentEditingModelFactory(ITemplateService templateService) { _templateService = templateService; } public async Task 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(); var variants = new List(); MapProperties(content, properties); MapNames(content, properties, variants); model.Properties = properties; model.Variants = variants; return model; } } private static void MapNames(IContent content, List properties, List 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 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, }); } } } } } }