/// <summary> /// Adds a complex region to a collection region. /// </summary> /// <typeparam name="T">The model type</typeparam> /// <param name="model">The model</param> /// <param name="contentType">The content type</param> /// <param name="regionId">The region id</param> /// <param name="fields">The field</param> private async Task AddComplexValueAsync <T>(T model, Models.ContentTypeBase contentType, string regionId, IList <TField> fields) where T : Models.ContentBase { if (fields.Count > 0) { if (model is Models.IDynamicContent dynamicModel) { var list = (IList)((IDictionary <string, object>)dynamicModel.Regions)[regionId]; var obj = await _factory.CreateDynamicRegionAsync(contentType, regionId); foreach (var field in fields) { if (((IDictionary <string, object>)obj).ContainsKey(field.FieldId)) { ((IDictionary <string, object>)obj)[field.FieldId] = DeserializeValue(field); } } list.Add(obj); } else { var regionProp = model.GetType().GetProperty(regionId, App.PropertyBindings); if (regionProp != null) { var list = (IList)regionProp.GetValue(model); var obj = Activator.CreateInstance(list.GetType().GenericTypeArguments.First()); foreach (var field in fields) { var fieldProp = obj.GetType().GetProperty(field.FieldId, App.PropertyBindings); if (fieldProp != null) { fieldProp.SetValue(obj, DeserializeValue(field)); } } list.Add(obj); } } } }
/// <summary> /// Loads the given data into a new model. /// </summary> /// <typeparam name="T">The model type</typeparam> /// <param name="content">The content entity</param> /// <param name="type">The content type</param> /// <param name="process">Optional func that should be called after transformation</param> /// <returns>The page model</returns> public async Task <T> TransformAsync <T>(TContent content, Models.ContentTypeBase type, Func <TContent, T, Task> process = null) where T : Models.ContentBase, TModelBase { if (type != null) { var modelType = typeof(T); if (!typeof(Models.IDynamicContent).IsAssignableFrom(modelType) && !typeof(Models.IContentInfo).IsAssignableFrom(modelType)) { modelType = Type.GetType(type.CLRType); if (modelType != typeof(T) && !typeof(T).IsAssignableFrom(modelType)) { return(null); } } // Create an initialized model var model = await _factory.CreateAsync <T>(type); // Map basic fields _mapper.Map <TContent, TModelBase>(content, model); if (model is Models.RoutedContentBase routeModel) { // Map route (if available) if (string.IsNullOrWhiteSpace(routeModel.Route) && type.Routes.Count > 0) { routeModel.Route = type.Routes.First(); } } // Map regions if (!(model is IContentInfo)) { var currentRegions = type.Regions.Select(r => r.Id).ToArray(); foreach (var regionKey in currentRegions) { var region = type.Regions.Single(r => r.Id == regionKey); var fields = content.Fields.Where(f => f.RegionId == regionKey).OrderBy(f => f.SortOrder).ToList(); if (!region.Collection) { foreach (var fieldDef in region.Fields) { var field = fields.SingleOrDefault(f => f.FieldId == fieldDef.Id && f.SortOrder == 0); if (field != null) { if (region.Fields.Count == 1) { SetSimpleValue(model, regionKey, field); break; } else { SetComplexValue(model, regionKey, fieldDef.Id, field); } } } } else { var fieldCount = content.Fields.Where(f => f.RegionId == regionKey).Select(f => f.SortOrder).DefaultIfEmpty(-1).Max() + 1; var sortOrder = 0; while (fieldCount > sortOrder) { if (region.Fields.Count == 1) { var field = fields.SingleOrDefault(f => f.FieldId == region.Fields[0].Id && f.SortOrder == sortOrder); if (field != null) { AddSimpleValue(model, regionKey, field); } } else { await AddComplexValueAsync(model, type, regionKey, fields.Where(f => f.SortOrder == sortOrder).ToList()) .ConfigureAwait(false); } sortOrder++; } } } } if (process != null) { await process(content, model); } return(model); } return(null); }
/// <summary> /// Loads the given data into a new model. /// </summary> /// <typeparam name="T">The model type</typeparam> /// <param name="content">The content entity</param> /// <param name="type">The content type</param> /// <param name="process">Optional func that should be called after transformation</param> /// <param name="languageId">The optional language id</param> /// <returns>The page model</returns> public async Task <T> TransformAsync <T>(TContent content, Models.ContentTypeBase type, Func <TContent, T, Task> process = null, Guid?languageId = null) where T : Models.ContentBase, TModelBase { if (content is Content genericContent) { // We need the currently selected language id for mapping. genericContent.SelectedLanguageId = languageId; } if (type != null) { // // 1: Get the requested model type // var modelType = typeof(T); if (!typeof(Models.IDynamicContent).IsAssignableFrom(modelType) && !typeof(Models.IContentInfo).IsAssignableFrom(modelType)) { modelType = Type.GetType(type.CLRType); if (modelType != typeof(T) && !typeof(T).IsAssignableFrom(modelType)) { return(null); } } // // 2: Create an initialized model // var model = await _factory.CreateAsync <T>(type); // // 3: Map basic fields // _mapper.Map <TContent, TModelBase>(content, model); // // 4: Map routes // if (model is Models.RoutedContentBase routeModel) { // Map route (if available) if (string.IsNullOrWhiteSpace(routeModel.Route) && type.Routes.Count > 0) { routeModel.Route = type.Routes.First(); } } // // 5: Map translation // if (content is ITranslatable translatableContent && languageId.HasValue) { var translation = translatableContent.GetTranslation(languageId.Value); if (translation != null) { _mapper.Map(translation, model); } } // // 6: Map regions // if (!(model is IContentInfo)) { var currentRegions = type.Regions.Select(r => r.Id).ToArray(); foreach (var regionKey in currentRegions) { var region = type.Regions.Single(r => r.Id == regionKey); var fields = content.Fields.Where(f => f.RegionId == regionKey).OrderBy(f => f.SortOrder).ToList(); if (!region.Collection) { foreach (var fieldDef in region.Fields) { var field = fields.SingleOrDefault(f => f.FieldId == fieldDef.Id && f.SortOrder == 0); if (field != null) { if (region.Fields.Count == 1) { SetSimpleValue(model, regionKey, field, languageId); break; } else { SetComplexValue(model, regionKey, fieldDef.Id, field, languageId); } } } } else { var fieldCount = content.Fields.Where(f => f.RegionId == regionKey).Select(f => f.SortOrder).DefaultIfEmpty(-1).Max() + 1; var sortOrder = 0; while (fieldCount > sortOrder) { if (region.Fields.Count == 1) { var field = fields.SingleOrDefault(f => f.FieldId == region.Fields[0].Id && f.SortOrder == sortOrder); if (field != null) { AddSimpleValue(model, regionKey, field, languageId); } } else { await AddComplexValueAsync(model, type, regionKey, fields.Where(f => f.SortOrder == sortOrder).ToList(), languageId) .ConfigureAwait(false); } sortOrder++; } } } } if (process != null) { await process(content, model).ConfigureAwait(false); } return(model); } return(null); }
/// <summary> /// Transforms the given model into content data. /// </summary> /// <param name="model">The model</param> /// <param name="type">The conten type</param> /// <param name="dest">The optional dest object</param> /// <returns>The content data</returns> public TContent Transform <T>(T model, Models.ContentTypeBase type, TContent dest = null) where T : Models.ContentBase, TModelBase { var content = dest == null?Activator.CreateInstance <TContent>() : dest; // Map id if (model.Id != Guid.Empty) { content.Id = model.Id; } else { content.Id = model.Id = Guid.NewGuid(); } content.Created = DateTime.Now; // Map basic fields _mapper.Map <TModelBase, TContent>(model, content); // Map regions var currentRegions = type.Regions.Select(r => r.Id).ToArray(); foreach (var regionKey in currentRegions) { // Check that the region exists in the current model if (HasRegion(model, regionKey)) { var regionType = type.Regions.Single(r => r.Id == regionKey); if (!regionType.Collection) { MapRegion(content, GetRegion(model, regionKey), regionType, regionKey); } else { var items = new List <Guid>(); var sortOrder = 0; foreach (var region in GetEnumerable(model, regionKey)) { var fields = MapRegion(content, region, regionType, regionKey, sortOrder++); if (fields.Count > 0) { items.AddRange(fields); } } // Now delete removed collection items var removedFields = content.Fields .Where(f => f.RegionId == regionKey && !items.Contains(f.Id)) .ToList(); foreach (var removed in removedFields) { content.Fields.Remove(removed); } } } } return(content); }
/// <summary> /// Transforms the given model into content data. /// </summary> /// <param name="model">The model</param> /// <param name="type">The conten type</param> /// <param name="dest">The optional dest object</param> /// <param name="languageId">The optional language id</param> /// <returns>The content data</returns> public TContent Transform <T>(T model, Models.ContentTypeBase type, TContent dest = null, Guid?languageId = null) where T : Models.ContentBase, TModelBase { var content = dest == null?Activator.CreateInstance <TContent>() : dest; // // 1: Map id // if (model.Id != Guid.Empty) { content.Id = model.Id; } else { content.Id = model.Id = Guid.NewGuid(); } content.Created = DateTime.Now; // // 2: Map basic fields // _mapper.Map <TModelBase, TContent>(model, content); // // 3: Map translation // if (content is ITranslatable translatableContent && languageId.HasValue) { translatableContent.SetTranslation(content.Id, languageId.Value, model); } // // 4: Map category // if (model is Models.ICategorizedContent categorized) { if (content is ICategorized categorizedContent) { categorizedContent.CategoryId = categorized.Category.Id; } } // // 5: Map regions // var currentRegions = type.Regions.Select(r => r.Id).ToArray(); foreach (var regionKey in currentRegions) { // Check that the region exists in the current model if (HasRegion(model, regionKey)) { var regionType = type.Regions.Single(r => r.Id == regionKey); if (!regionType.Collection) { MapRegion(content, GetRegion(model, regionKey), regionType, regionKey, languageId: languageId); } else { var items = new List <Guid>(); var sortOrder = 0; foreach (var region in GetEnumerable(model, regionKey)) { var fields = MapRegion(content, region, regionType, regionKey, sortOrder++, languageId); if (fields.Count > 0) { items.AddRange(fields); } } // Now delete removed collection items var removedFields = content.Fields .Where(f => f.RegionId == regionKey && !items.Contains(f.Id)) .ToList(); foreach (var removed in removedFields) { content.Fields.Remove(removed); } } } } return(content); }