private static MediaVersionDto BuildMediaVersionDto(PropertyEditorCollection propertyEditors, IMedia entity, ContentDto contentDto) { // try to get a path from the string being stored for media // TODO: only considering umbracoFile string path = null; if (entity.Properties.TryGetValue(Constants.Conventions.Media.File, out var property) && propertyEditors.TryGet(property.PropertyType.PropertyEditorAlias, out var editor) && editor is IDataEditorWithMediaPath dataEditor) { var value = property.GetValue(); path = dataEditor.GetMediaPath(value); } var dto = new MediaVersionDto { Id = entity.VersionId, Path = path, ContentVersionDto = BuildContentVersionDto(entity, contentDto) }; return(dto); }
public void Initialize() { DataTypeService.Deleting += StopFormRteDelete; if (_dataTypeService.GetDataType(FormRteName) != null || !_propertyEditorCollection.TryGet(Constants.PropertyEditors.Aliases.TinyMce, out var editor)) { return; } var formsRTE = new DataType(editor) { Name = FormRteName, Configuration = new Dictionary <string, object> { ["editor"] = new Dictionary <string, object> { ["toolbar"] = new[] { "ace", "bold", "italic", "bullist", "numlist", "link", "umbmediapicker" }, ["stylesheets"] = new string[0], ["maxImageSize"] = 500, ["mode"] = "classic" }, ["hideLabel"] = false, ["ignoreUserStartNodes"] = false, ["mediaParentId"] = null } }; _dataTypeService.Save(formsRTE); }
private Dictionary <string, IPublishedProperty> MapProperties(ServiceContext services) { var contentType = this.contentType.Value; var properties = this.content.Properties; var items = new Dictionary <string, IPublishedProperty>(StringComparer.InvariantCultureIgnoreCase); foreach (var propertyType in contentType.PropertyTypes) { var property = properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyType.DataType.EditorAlias)); var value = property?.GetValue(); if (value != null) { _propertyEditors.TryGet(propertyType.DataType.EditorAlias, out var editor); if (editor != null) { value = editor.GetValueEditor().ConvertDbToString(property.PropertyType, value, services.DataTypeService); } } items.Add(propertyType.DataType.EditorAlias, new UnpublishedProperty(propertyType, value)); } return(items); }
/// <inheritdoc /> public virtual UrlInfo GetMediaUrl(UmbracoContext umbracoContext, IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current) { var prop = content.GetProperty(propertyAlias); // get the raw source value since this is what is used by IDataEditorWithMediaPath for processing var value = prop?.GetSourceValue(culture); if (value == null) { return(null); } var propType = prop.PropertyType; string path = null; if (_propertyEditors.TryGet(propType.EditorAlias, out var editor) && editor is IDataEditorWithMediaPath dataEditor) { path = dataEditor.GetMediaPath(value); } var url = AssembleUrl(path, current, mode); return(url == null ? null : UrlInfo.Url(url.ToString(), culture)); }
// Umbraco.Code.MapAll -HasPrevalues private void Map(IDataType source, DataTypeBasic target, MapperContext context) { target.Id = source.Id; target.IsSystemDataType = SystemIds.Contains(source.Id); target.Key = source.Key; target.Name = source.Name; target.ParentId = source.ParentId; target.Path = source.Path; target.Trashed = source.Trashed; target.Udi = Udi.Create(Constants.UdiEntityType.DataType, source.Key); if (!_propertyEditors.TryGet(source.EditorAlias, out var editor)) { return; } target.Alias = editor.Alias; target.Group = editor.Group; target.Icon = editor.Icon; }
// TODO: We could further reduce circular dependencies with PropertyEditorCollection by not having IDataValueReference implemented // by property editors and instead just use the already built in IDataValueReferenceFactory and/or refactor that into a more normal collection public IEnumerable <UmbracoEntityReference> GetAllReferences( IPropertyCollection properties, PropertyEditorCollection propertyEditors) { var trackedRelations = new HashSet <UmbracoEntityReference>(); foreach (IProperty p in properties) { if (!propertyEditors.TryGet(p.PropertyType.PropertyEditorAlias, out IDataEditor? editor)) { continue; } // TODO: We will need to change this once we support tracking via variants/segments // for now, we are tracking values from ALL variants foreach (IPropertyValue propertyVal in p.Values) { var val = propertyVal.EditedValue; IDataValueEditor?valueEditor = editor?.GetValueEditor(); if (valueEditor is IDataValueReference reference) { IEnumerable <UmbracoEntityReference> refs = reference.GetReferences(val); foreach (UmbracoEntityReference r in refs) { trackedRelations.Add(r); } } // Loop over collection that may be add to existing property editors // implementation of GetReferences in IDataValueReference. // Allows developers to add support for references by a // package /property editor that did not implement IDataValueReference themselves foreach (IDataValueReferenceFactory item in this) { // Check if this value reference is for this datatype/editor // Then call it's GetReferences method - to see if the value stored // in the dataeditor/property has referecnes to media/content items if (item.IsForEditor(editor)) { foreach (UmbracoEntityReference r in item.GetDataValueReference().GetReferences(val)) { trackedRelations.Add(r); } } } } } return(trackedRelations); }
public HttpResponseMessage GetPreview([FromBody] JObject data) { var config = data.ToObject <Dictionary <string, object> >(); if (_propertyEditors.TryGet(DataListDataEditor.DataEditorAlias, out var propertyEditor) == true) { var alias = config.GetValueAs("alias", "preview"); var configurationEditor = propertyEditor.GetConfigurationEditor(); var valueEditorConfig = configurationEditor.ToValueEditor(config); var valueEditor = propertyEditor.GetValueEditor(config); return(Request.CreateResponse(HttpStatusCode.OK, new { config = valueEditorConfig, view = valueEditor.View, alias })); } return(Request.CreateResponse(HttpStatusCode.NotFound)); }
public static IDataType BuildEntity(DataTypeDto dto, PropertyEditorCollection editors, ILogger <IDataType> logger, IConfigurationEditorJsonSerializer serializer) { // Check we have an editor for the data type. if (!editors.TryGet(dto.EditorAlias, out IDataEditor? editor)) { logger.LogWarning( "Could not find an editor with alias {EditorAlias}, treating as Label. " + "The site may fail to boot and/or load data types and run.", dto.EditorAlias); // Create as special type, which downstream can be handled by converting to a LabelPropertyEditor to make clear // the situation to the user. editor = new MissingPropertyEditor(); } var dataType = new DataType(editor, serializer); try { dataType.DisableChangeTracking(); dataType.CreateDate = dto.NodeDto.CreateDate; dataType.DatabaseType = dto.DbType.EnumParse <ValueStorageType>(true); dataType.Id = dto.NodeId; dataType.Key = dto.NodeDto.UniqueId; dataType.Level = dto.NodeDto.Level; dataType.UpdateDate = dto.NodeDto.CreateDate; dataType.Name = dto.NodeDto.Text; dataType.ParentId = dto.NodeDto.ParentId; dataType.Path = dto.NodeDto.Path; dataType.SortOrder = dto.NodeDto.SortOrder; dataType.Trashed = dto.NodeDto.Trashed; dataType.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId; dataType.SetLazyConfiguration(dto.Configuration); // reset dirty initial properties (U4-1946) dataType.ResetDirtyProperties(false); return(dataType); } finally { dataType.EnableChangeTracking(); } }
private static void SetUploadFile(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) { var property = GetProperty(content, contentTypeBaseServiceProvider, propertyTypeAlias); // Fixes https://github.com/umbraco/Umbraco-CMS/issues/3937 - Assigning a new file to an // existing IMedia with extension SetValue causes exception 'Illegal characters in path' string oldpath = null; var value = property.GetValue(culture, segment); if (PropertyEditors.TryGet(propertyTypeAlias, out var editor) && editor is IDataEditorWithMediaPath dataEditor) { var svalue = dataEditor.GetMediaPath(value); oldpath = MediaFileSystem.GetRelativePath(svalue); } var filepath = MediaFileSystem.StoreFile(content, property.PropertyType, filename, filestream, oldpath); property.SetValue(MediaFileSystem.GetUrl(filepath), culture, segment); }
public static IDataType BuildEntity(DataTypeDto dto, PropertyEditorCollection editors, ILogger logger) { if (!editors.TryGet(dto.EditorAlias, out var editor)) { logger.Warn(typeof(DataType), "Could not find an editor with alias {EditorAlias}, treating as Label." + " The site may fail to boot and / or load data types and run.", dto.EditorAlias); //convert to label editor = new LabelPropertyEditor(logger); } var dataType = new DataType(editor); try { dataType.DisableChangeTracking(); dataType.CreateDate = dto.NodeDto.CreateDate; dataType.DatabaseType = dto.DbType.EnumParse <ValueStorageType>(true); dataType.Id = dto.NodeId; dataType.Key = dto.NodeDto.UniqueId; dataType.Level = dto.NodeDto.Level; dataType.UpdateDate = dto.NodeDto.CreateDate; dataType.Name = dto.NodeDto.Text; dataType.ParentId = dto.NodeDto.ParentId; dataType.Path = dto.NodeDto.Path; dataType.SortOrder = dto.NodeDto.SortOrder; dataType.Trashed = dto.NodeDto.Trashed; dataType.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId; dataType.SetLazyConfiguration(dto.Configuration); // reset dirty initial properties (U4-1946) dataType.ResetDirtyProperties(false); return(dataType); } finally { dataType.EnableChangeTracking(); } }
private void CreateExampleBlockDataType(string contentTypeAlias, Guid dataTypeKey) { if (_dataTypeService.GetDataType(dataTypeKey) != null) { // Already there return; } if (!(_propertyEditors.TryGet("Umbraco.NestedContent", out var editor) && editor is NestedContentPropertyEditor nestedContentEditor)) { throw new InvalidOperationException("Nested Content property editor not found!"); } var dataType = new DataType(nestedContentEditor, -1) { Name = "Perplex.ContentBlocks - ExampleBlock", Key = dataTypeKey, Configuration = new NestedContentConfiguration { ConfirmDeletes = false, HideLabel = true, MinItems = 1, MaxItems = 1, ShowIcons = false, ContentTypes = new[] { new NestedContentConfiguration.ContentType { Alias = contentTypeAlias, TabAlias = "Content", Template = "{{title}}" } } } }; _dataTypeService.Save(dataType); }
public static IDataType BuildEntity(DataTypeDto dto, PropertyEditorCollection editors) { if (!editors.TryGet(dto.EditorAlias, out var editor)) { throw new InvalidOperationException($"Could not find an editor with alias \"{dto.EditorAlias}\"."); } var dataType = new DataType(editor); try { dataType.DisableChangeTracking(); dataType.CreateDate = dto.NodeDto.CreateDate; dataType.DatabaseType = dto.DbType.EnumParse <ValueStorageType>(true); dataType.Id = dto.NodeId; dataType.Key = dto.NodeDto.UniqueId; dataType.Level = dto.NodeDto.Level; dataType.UpdateDate = dto.NodeDto.CreateDate; dataType.Name = dto.NodeDto.Text; dataType.ParentId = dto.NodeDto.ParentId; dataType.Path = dto.NodeDto.Path; dataType.SortOrder = dto.NodeDto.SortOrder; dataType.Trashed = dto.NodeDto.Trashed; dataType.CreatorId = dto.NodeDto.UserId ?? Constants.Security.UnknownUserId; dataType.SetLazyConfiguration(dto.Configuration); // reset dirty initial properties (U4-1946) dataType.ResetDirtyProperties(false); return(dataType); } finally { dataType.EnableChangeTracking(); } }
private IPublishedElement ConvertValue(string id, string contentTypeAlias, string dataJson) { var contentTypes = GetContentTypesByAlias(contentTypeAlias); var properties = new List <IPublishedProperty>(); // Convert all the properties var data = JsonConvert.DeserializeObject(dataJson); var propValues = ((JObject)data).ToObject <Dictionary <string, object> >(); foreach (var jProp in propValues) { var propType = contentTypes.PublishedContentType.GetPropertyType(jProp.Key); if (propType == null) { continue; } /* Because we never store the value in the database, we never run the property editors * "ConvertEditorToDb" method however the property editors will expect their value to * be in a "DB" state so to get round this, we run the "ConvertEditorToDb" here before * we go on to convert the value for the view. */ _dataEditors.TryGet(propType.EditorAlias, out var propEditor); var propPreValues = GetPreValuesCollectionByDataTypeId(propType.DataType.Id); var contentPropData = new ContentPropertyData(jProp.Value, propPreValues); var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, jProp.Value); // Performing "ValueProcessing" if any ValueProcessor is configured for this Property Editor-alias. // TODO: Process values //var processorsCollection = Current.Factory.GetInstance<DocTypeGridEditorValueProcessorsCollection>(); //var processor = processorsCollection.FirstOrDefault(x => x.IsProcessorFor(propEditor.Alias)); //if (processor != null) //{ // newValue = processor.ProcessValue(newValue); //} /* Now that we have the DB stored value, we actually need to then convert it into its * XML serialized state as expected by the published property by calling ConvertDbToString */ var propType2 = contentTypes.ContentType.CompositionPropertyTypes.First(x => x.PropertyEditorAlias.InvariantEquals(propType.DataType.EditorAlias)); Property prop2 = null; try { /* HACK: [LK:2016-04-01] When using the "Umbraco.Tags" property-editor, the converted DB value does * not match the datatypes underlying db-column type. So it throws a "Type validation failed" exception. * We feel that the Umbraco core isn't handling the Tags value correctly, as it should be the responsiblity * of the "Umbraco.Tags" property-editor to handle the value conversion into the correct type. * See: http://issues.umbraco.org/issue/U4-8279 */ prop2 = new Property(propType2); prop2.SetValue(newValue); } catch (Exception ex) { _logger.LogError(new EventId(0), ex, "[DocTypeGridEditor] Error creating Property object."); } if (prop2 != null) { var newValue2 = propEditor.GetValueEditor().ConvertDbToString(propType2, newValue, _dataTypeService); properties.Add(new DetachedPublishedProperty(propType, newValue2)); } } // Manually parse out the special properties propValues.TryGetValue("name", out object nameObj); Guid.TryParse(id, out Guid key); // Get the current request node we are embedded in var pcr = _umbracoContext.UmbracoContext.PublishedRequest; var containerNode = pcr != null && pcr.HasPublishedContent() ? pcr.PublishedContent : null; // Create the model based on our implementation of IPublishedElement IPublishedElement content = new DetachedPublishedElement( key, contentTypes.PublishedContentType, properties.ToArray()); if (_publishedModelFactory != null) { // Let the current model factory create a typed model to wrap our model content = _publishedModelFactory.CreateModel(content); } return(content); }
public override PipelineResult <InstallPipelineContext> Execute(PipelineArgs <InstallPipelineContext> args) { // Theme Color Picker var currentColorPicker = _dataTypeService.GetDataType(VendrCheckoutConstants.DataTypes.Guids.ThemeColorPickerGuid); if (currentColorPicker == null) { if (_propertyEditors.TryGet(Constants.PropertyEditors.Aliases.ColorPicker, out IDataEditor editor)) { var dataType = CreateDataType(editor, x => { x.Key = VendrCheckoutConstants.DataTypes.Guids.ThemeColorPickerGuid; x.Name = "[Vendr Checkout] Theme Color Picker"; x.DatabaseType = ValueStorageType.Nvarchar; x.Configuration = new ColorPickerConfiguration { Items = VendrCheckoutConstants.ColorMap.Select((kvp, idx) => new ValueListConfiguration.ValueListItem { Id = idx, Value = "{\"value\":\"" + kvp.Key + "\", \"label\":\"" + kvp.Value + "\"}" }).ToList(), UseLabel = false }; }); _dataTypeService.Save(dataType); } } else { currentColorPicker.Configuration = new ColorPickerConfiguration { Items = VendrCheckoutConstants.ColorMap.Select((kvp, idx) => new ValueListConfiguration.ValueListItem { Id = idx, Value = "{\"value\":\"" + kvp.Key + "\", \"label\":\"" + kvp.Value + "\"}" }).ToList(), UseLabel = false }; _dataTypeService.Save(currentColorPicker); } // Step Picker var stepPickerItems = new List <ValueListConfiguration.ValueListItem> { new ValueListConfiguration.ValueListItem { Id = 1, Value = "Information" }, new ValueListConfiguration.ValueListItem { Id = 2, Value = "ShippingMethod" }, new ValueListConfiguration.ValueListItem { Id = 3, Value = "PaymentMethod" }, new ValueListConfiguration.ValueListItem { Id = 4, Value = "Review" }, new ValueListConfiguration.ValueListItem { Id = 5, Value = "Payment" }, new ValueListConfiguration.ValueListItem { Id = 6, Value = "Confirmation" } }; var currentStepPicker = _dataTypeService.GetDataType(VendrCheckoutConstants.DataTypes.Guids.StepPickerGuid); if (currentStepPicker == null) { if (_propertyEditors.TryGet(Constants.PropertyEditors.Aliases.DropDownListFlexible, out IDataEditor editor)) { var dataType = CreateDataType(editor, x => { x.Key = VendrCheckoutConstants.DataTypes.Guids.StepPickerGuid; x.Name = "[Vendr Checkout] Step Picker"; x.DatabaseType = ValueStorageType.Nvarchar; x.Configuration = new DropDownFlexibleConfiguration { Items = stepPickerItems, Multiple = false }; }); _dataTypeService.Save(dataType); } } else { currentStepPicker.Configuration = new DropDownFlexibleConfiguration { Items = stepPickerItems, Multiple = false }; _dataTypeService.Save(currentStepPicker); } // Continue the pipeline return(Ok()); }
protected override void Migrate() { // drop and create columns Delete.Column("pk").FromTable("cmsDataType").Do(); // rename the table Rename.Table("cmsDataType").To(Cms.Core.Constants.DatabaseSchema.Tables.DataType).Do(); // create column AddColumn <DataTypeDto>(Cms.Core.Constants.DatabaseSchema.Tables.DataType, "config"); Execute.Sql(Sql().Update <DataTypeDto>(u => u.Set(x => x.Configuration, string.Empty))).Do(); // renames Execute.Sql(Sql() .Update <DataTypeDto>(u => u.Set(x => x.EditorAlias, "Umbraco.ColorPicker")) .Where <DataTypeDto>(x => x.EditorAlias == "Umbraco.ColorPickerAlias")).Do(); // from preValues to configuration... var sql = Sql() .Select <DataTypeDto>() .AndSelect <PreValueDto>(x => x.Id, x => x.Alias, x => x.SortOrder, x => x.Value) .From <DataTypeDto>() .InnerJoin <PreValueDto>().On <DataTypeDto, PreValueDto>((left, right) => left.NodeId == right.NodeId) .OrderBy <DataTypeDto>(x => x.NodeId) .AndBy <PreValueDto>(x => x.SortOrder); var dtos = Database.Fetch <PreValueDto>(sql).GroupBy(x => x.NodeId); foreach (var group in dtos) { var dataType = Database.Fetch <DataTypeDto>(Sql() .Select <DataTypeDto>() .From <DataTypeDto>() .Where <DataTypeDto>(x => x.NodeId == group.Key)).First(); // check for duplicate aliases var aliases = group.Select(x => x.Alias).Where(x => !string.IsNullOrWhiteSpace(x)).ToArray(); if (aliases.Distinct().Count() != aliases.Length) { throw new InvalidOperationException($"Cannot migrate prevalues for datatype id={dataType.NodeId}, editor={dataType.EditorAlias}: duplicate alias."); } // handle null/empty aliases int index = 0; var dictionary = group.ToDictionary(x => string.IsNullOrWhiteSpace(x.Alias) ? index++.ToString() : x.Alias); // migrate the preValues to configuration var migrator = _preValueMigrators.GetMigrator(dataType.EditorAlias) ?? new DefaultPreValueMigrator(); var config = migrator.GetConfiguration(dataType.NodeId, dataType.EditorAlias, dictionary); var json = _configurationEditorJsonSerializer.Serialize(config); // validate - and kill the migration if it fails var newAlias = migrator.GetNewAlias(dataType.EditorAlias); if (newAlias == null) { if (!LegacyAliases.Contains(dataType.EditorAlias)) { _logger.LogWarning( "Skipping validation of configuration for data type {NodeId} : {EditorAlias}." + " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.", dataType.NodeId, dataType.EditorAlias); } } else if (!_propertyEditors.TryGet(newAlias, out var propertyEditor)) { if (!LegacyAliases.Contains(newAlias)) { _logger.LogWarning("Skipping validation of configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})" + " because no property editor with that alias was found." + " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.", dataType.NodeId, newAlias, dataType.EditorAlias); } } else { var configEditor = propertyEditor.GetConfigurationEditor(); try { var _ = configEditor.FromDatabase(json, _configurationEditorJsonSerializer); } catch (Exception e) { _logger.LogWarning(e, "Failed to validate configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})." + " Please fix the configuration and ensure it is valid. The site may fail to start and / or load data types and run.", dataType.NodeId, newAlias, dataType.EditorAlias); } } // update dataType.Configuration = _configurationEditorJsonSerializer.Serialize(config); Database.Update(dataType); } }
public virtual IPublishedElement[] ParseElements(IPublishedElement parent, JArray array) { if (array == null) { return(new IPublishedElement[0]); } List <IPublishedElement> items = new List <IPublishedElement>(); foreach (JObject item in array) { // Get basic information from the item Guid key = item.GetGuid("key"); string name = item.GetString("name"); Guid contentTypeKey = item.GetGuid("contentType"); // Get a reference to the content type IContentType contentType = _contentTypeService.Get(contentTypeKey); if (contentType == null) { _logger.Error(typeof(PublishedElementHelper), "Content type with key " + contentTypeKey + " not found."); continue; } // Convert the content type to it's published counterpart IPublishedContentType pct = _publishedContentTypeFactory.CreateContentType(contentType); // Initialize a new collection of properties List <IPublishedProperty> properties = new List <IPublishedProperty>(); // Create the model based on our implementation of IPublishedElement IPublishedElement element = new SkybrudPublishedElement(parent, key, name, pct, properties); foreach (JProperty prop in item.GetObject("properties").Properties()) { // Get a reference to the property type IPublishedPropertyType type = pct.GetPropertyType(prop.Name); if (type == null) { //_logger.Error<PublishedElementHelper>("Property type for property with alias {Alias} not found.", prop.Name); continue; } // Get a reference to the property editor if (_propertyEditors.TryGet(type.EditorAlias, out IDataEditor propEditor) == false) { _logger.Error <PublishedElementHelper>("Property editor with alias {Alias} not found.", type.EditorAlias); continue; } #region Borrowed from Doc Type Grid Editor ContentPropertyData contentPropData = new ContentPropertyData(prop.Value, type.DataType.Configuration); object newValue = prop.Value == null ? null : propEditor.GetValueEditor().FromEditor(contentPropData, prop.Value); PropertyType propType2; try { propType2 = contentType.CompositionPropertyTypes.First(x => x.PropertyEditorAlias.InvariantEquals(type.DataType.EditorAlias)); } catch (Exception ex) { throw new ElementsException($"Unable to find property editor with alias: {type.DataType.EditorAlias} (" + type.DataType.Id + ")", ex); } Property prop2 = null; try { /* HACK: [LK:2016-04-01] When using the "Umbraco.Tags" property-editor, the converted DB value does * not match the datatypes underlying db-column type. So it throws a "Type validation failed" exception. * We feel that the Umbraco core isn't handling the Tags value correctly, as it should be the responsiblity * of the "Umbraco.Tags" property-editor to handle the value conversion into the correct type. * See: http://issues.umbraco.org/issue/U4-8279 */ prop2 = new Property(propType2); prop2.SetValue(newValue); } catch (Exception ex) { _logger.Error(typeof(PublishedElementHelper), ex, "Error creating Property object."); } if (prop2 != null) { string newValue2 = propEditor.GetValueEditor().ConvertDbToString(propType2, newValue, _dataTypeService); properties.Add(new SkybrudPublishedProperty(element, type, prop.Name, newValue2)); } #endregion } // Let the current model factory create a typed model to wrap our model if (_publishedModelFactory != null) { element = _publishedModelFactory.CreateModel(element); } items.Add(element); } return(items.ToArray()); }
public void OnActionExecuting(ActionExecutingContext context) { var dataType = (DataTypeSave?)context.ActionArguments["dataType"]; if (dataType is not null) { dataType.Name = dataType.Name?.CleanForXss('[', ']', '(', ')', ':'); dataType.Alias = dataType.Alias == null ? dataType.Name ! : dataType.Alias.CleanForXss('[', ']', '(', ')', ':'); } // get the property editor, ensuring that it exits if (!_propertyEditorCollection.TryGet(dataType?.EditorAlias, out var propertyEditor)) { var message = $"Property editor \"{dataType?.EditorAlias}\" was not found."; context.Result = new UmbracoProblemResult(message, HttpStatusCode.NotFound); return; } if (dataType is null) { return; } // assign dataType.PropertyEditor = propertyEditor; // validate that the data type exists, or create one if required IDataType?persisted; switch (dataType.Action) { case ContentSaveAction.Save: persisted = _dataTypeService.GetDataType(Convert.ToInt32(dataType.Id)); if (persisted == null) { var message = $"Data type with id {dataType.Id} was not found."; context.Result = new UmbracoProblemResult(message, HttpStatusCode.NotFound); return; } // map the model to the persisted instance _umbracoMapper.Map(dataType, persisted); break; case ContentSaveAction.SaveNew: // create the persisted model from mapping the saved model persisted = _umbracoMapper.Map <IDataType>(dataType); ((DataType?)persisted)?.ResetIdentity(); break; default: context.Result = new UmbracoProblemResult($"Data type action {dataType.Action} was not found.", HttpStatusCode.NotFound); return; } // assign (so it's available in the action) dataType.PersistedDataType = persisted; // validate the configuration // which is posted as a set of fields with key (string) and value (object) var configurationEditor = propertyEditor.GetConfigurationEditor(); if (dataType.ConfigurationFields is not null) { foreach (var field in dataType.ConfigurationFields) { var editorField = configurationEditor.Fields.SingleOrDefault(x => x.Key == field.Key); if (editorField == null) { continue; } // run each IValueValidator (with null valueType and dataTypeConfiguration: not relevant here) foreach (var validator in editorField.Validators) { foreach (var result in validator.Validate(field.Value, null, null)) { context.ModelState.AddValidationError(result, "Properties", field.Key ?? string.Empty); } } } } if (context.ModelState.IsValid == false) { // if it is not valid, do not continue and return the model state context.Result = new ValidationErrorResult(context.ModelState); } }
public override void Migrate() { // drop and create columns Delete.Column("pk").FromTable("cmsDataType").Do(); // rename the table Rename.Table("cmsDataType").To(Constants.DatabaseSchema.Tables.DataType).Do(); // create column AddColumn <DataTypeDto>(Constants.DatabaseSchema.Tables.DataType, "config"); Execute.Sql(Sql().Update <DataTypeDto>(u => u.Set(x => x.Configuration, string.Empty))).Do(); // renames Execute.Sql(Sql() .Update <DataTypeDto>(u => u.Set(x => x.EditorAlias, "Umbraco.ColorPicker")) .Where <DataTypeDto>(x => x.EditorAlias == "Umbraco.ColorPickerAlias")).Do(); // from preValues to configuration... var sql = Sql() .Select <DataTypeDto>() .AndSelect <PreValueDto>(x => x.Id, x => x.Alias, x => x.SortOrder, x => x.Value) .From <DataTypeDto>() .InnerJoin <PreValueDto>().On <DataTypeDto, PreValueDto>((left, right) => left.NodeId == right.NodeId) .OrderBy <DataTypeDto>(x => x.NodeId) .AndBy <PreValueDto>(x => x.SortOrder); var dtos = Database.Fetch <PreValueDto>(sql).GroupBy(x => x.NodeId); foreach (var group in dtos) { var dataType = Database.Fetch <DataTypeDto>(Sql() .Select <DataTypeDto>() .From <DataTypeDto>() .Where <DataTypeDto>(x => x.NodeId == group.Key)).First(); // migrate the preValues to configuration var migrator = _preValueMigrators.GetMigrator(dataType.EditorAlias) ?? new DefaultPreValueMigrator(); var config = migrator.GetConfiguration(dataType.NodeId, dataType.EditorAlias, group.ToDictionary(x => x.Alias, x => x)); var json = JsonConvert.SerializeObject(config); // validate - and kill the migration if it fails var newAlias = migrator.GetNewAlias(dataType.EditorAlias); if (newAlias == null) { _logger.Warn <DataTypeMigration>("Skipping validation of configuration for data type {NodeId} : {EditorAlias}." + " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.", dataType.NodeId, dataType.EditorAlias); } else if (!_propertyEditors.TryGet(newAlias, out var propertyEditor)) { _logger.Warn <DataTypeMigration>("Skipping validation of configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})" + " because no property editor with that alias was found." + " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.", dataType.NodeId, newAlias, dataType.EditorAlias); } else { var configEditor = propertyEditor.GetConfigurationEditor(); try { var _ = configEditor.FromDatabase(json); } catch (Exception e) { _logger.Warn <DataTypeMigration>(e, "Failed to validate configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})." + " Please fix the configuration and ensure it is valid. The site may fail to start and / or load data types and run.", dataType.NodeId, newAlias, dataType.EditorAlias); } } // update dataType.Configuration = JsonConvert.SerializeObject(config); Database.Update(dataType); } }
/// <summary> /// It is a converter for any value type that is "JSON" /// Unless it's in the Excluded Property Editors list /// The new MediaPicker 3 stores JSON but we want to use its own ValueConvertor /// </summary> /// <param name="propertyType"></param> /// <returns></returns> public override bool IsConverter(IPublishedPropertyType propertyType) => _propertyEditors.TryGet(propertyType.EditorAlias, out IDataEditor? editor) && editor.GetValueEditor().ValueType.InvariantEquals(ValueTypes.Json) && _excludedPropertyEditors.Contains(propertyType.EditorAlias) == false;
/// <summary> /// It is a converter for any value type that is "JSON" /// </summary> /// <param name="propertyType"></param> /// <returns></returns> public override bool IsConverter(PublishedPropertyType propertyType) { return(_propertyEditors.TryGet(propertyType.EditorAlias, out var editor) && editor.GetValueEditor().ValueType.InvariantEquals(ValueTypes.Json)); }