private PropertyCollection GetPropertyCollection(int id, Guid versionId, IMediaType contentType, DateTime createDate, DateTime updateDate) { var sql = new Sql(); sql.Select("*") .From <PropertyDataDto>() .InnerJoin <PropertyTypeDto>() .On <PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id) .Where <PropertyDataDto>(x => x.NodeId == id) .Where <PropertyDataDto>(x => x.VersionId == versionId); var propertyDataDtos = Database.Fetch <PropertyDataDto, PropertyTypeDto>(sql); var propertyFactory = new PropertyFactory(contentType, versionId, id, createDate, updateDate); var properties = propertyFactory.BuildEntity(propertyDataDtos); var newProperties = properties.Where(x => x.HasIdentity == false); foreach (var property in newProperties) { var propertyDataDto = new PropertyDataDto { NodeId = id, PropertyTypeId = property.PropertyTypeId, VersionId = versionId }; int primaryKey = Convert.ToInt32(Database.Insert(propertyDataDto)); property.Version = versionId; property.Id = primaryKey; } return(new PropertyCollection(properties)); }
//fixme - see https://github.com/umbraco/Umbraco-CMS/pull/3460#issuecomment-434903930 we need to not load any property data at all for media private void BuildProperty(EntitySlim entity, PropertyDataDto pdto) { // explain ?! var value = string.IsNullOrWhiteSpace(pdto.TextValue) ? pdto.VarcharValue : pdto.TextValue.ConvertToJsonIfPossible(); entity.AdditionalData[pdto.PropertyTypeDto.Alias] = new EntitySlim.PropertySlim(pdto.PropertyTypeDto.DataTypeDto.EditorAlias, value); }
private bool UpdateNestedPropertyDataDto(PropertyDataDto pd) { if (UpdateNestedContent(pd.TextValue, out string newValue)) { pd.TextValue = newValue; return(true); } return(false); }
private static PropertyDataDto BuildDto(int versionId, IProperty property, int?languageId, string?segment, object?value) { var dto = new PropertyDataDto { VersionId = versionId, PropertyTypeId = property.PropertyTypeId }; if (languageId.HasValue) { dto.LanguageId = languageId; } if (segment != null) { dto.Segment = segment; } if (property.ValueStorageType == ValueStorageType.Integer) { if (value is bool || property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.Boolean) { dto.IntegerValue = value != null && string.IsNullOrEmpty(value.ToString()) ? 0 : Convert.ToInt32(value); } else if (value != null && string.IsNullOrWhiteSpace(value.ToString()) == false && int.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { dto.IntegerValue = val; } } else if (property.ValueStorageType == ValueStorageType.Decimal && value != null) { if (decimal.TryParse(value.ToString(), out var val)) { dto.DecimalValue = val; // property value should be normalized already } } else if (property.ValueStorageType == ValueStorageType.Date && value != null && string.IsNullOrWhiteSpace(value.ToString()) == false) { if (DateTime.TryParse(value.ToString(), out DateTime date)) { dto.DateValue = date; } } else if (property.ValueStorageType == ValueStorageType.Ntext && value != null) { dto.TextValue = value.ToString(); } else if (property.ValueStorageType == ValueStorageType.Nvarchar && value != null) { dto.VarcharValue = value.ToString(); } return(dto); }
public IEnumerable <PropertyDataDto> BuildDto(IEnumerable <Property> properties) { var propertyDataDtos = new List <PropertyDataDto>(); foreach (var property in properties) { var dto = new PropertyDataDto { NodeId = _id, PropertyTypeId = property.PropertyTypeId, VersionId = _version }; //Check if property has an Id and set it, so that it can be updated if it already exists if (property.HasIdentity) { dto.Id = property.Id; } if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer) { if (property.Value is bool || property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.TrueFalseAlias) { dto.Integer = property.Value != null && string.IsNullOrEmpty(property.Value.ToString()) ? 0 : Convert.ToInt32(property.Value); } else { int val; if ((property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) && int.TryParse(property.Value.ToString(), out val)) { dto.Integer = val; } } } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) { DateTime date; if (DateTime.TryParse(property.Value.ToString(), out date)) { dto.Date = date; } } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext && property.Value != null) { dto.Text = property.Value.ToString(); } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Nvarchar && property.Value != null) { dto.VarChar = property.Value.ToString(); } propertyDataDtos.Add(dto); } return(propertyDataDtos); }
private bool UpdateRadioOrCheckboxPropertyDataDto(PropertyDataDto propData, ValueListConfiguration config, bool singleValue) { //Get the INT ids stored for this property/drop down int[] ids = null; if (!propData.VarcharValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.VarcharValue); } else if (!propData.TextValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.TextValue); } else if (propData.IntegerValue.HasValue) { ids = new[] { propData.IntegerValue.Value }; } //if there are INT ids, convert them to values based on the configuration if (ids == null || ids.Length <= 0) { return(false); } //map the ids to values var values = new List <string>(); var canConvert = true; foreach (var id in ids) { var val = config.Items.FirstOrDefault(x => x.Id == id); if (val != null) { values.Add(val.Value); } else { Logger.Warn <DropDownPropertyEditorsMigration>( "Could not find associated data type configuration for stored Id {DataTypeId}", id); canConvert = false; } } if (!canConvert) { return(false); } //The radio button only supports selecting a single value, so if there are multiple for some insane reason we can only use the first propData.VarcharValue = singleValue ? values[0] : JsonConvert.SerializeObject(values); propData.TextValue = null; propData.IntegerValue = null; return(true); }
internal bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config, bool isMultiple) { // Get the INT ids stored for this property/drop down int[]? ids = null; if (!propData.VarcharValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.VarcharValue); } else if (!propData.TextValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.TextValue); } else if (propData.IntegerValue.HasValue) { ids = new[] { propData.IntegerValue.Value }; } // if there are INT ids, convert them to values based on the configuration if (ids == null || ids.Length <= 0) { return(false); } // map ids to values var values = new List <string>(); var canConvert = true; foreach (var id in ids) { ValueListConfiguration.ValueListItem?val = config.Items.FirstOrDefault(x => x.Id == id); if (val?.Value != null) { values.Add(val.Value); continue; } Logger.LogWarning( "Could not find PropertyData {PropertyDataId} value '{PropertyValue}' in the datatype configuration: {Values}.", propData.Id, id, string.Join(", ", config.Items.Select(x => x.Id + ":" + x.Value))); canConvert = false; } if (!canConvert) { return(false); } propData.VarcharValue = isMultiple ? JsonConvert.SerializeObject(values) : values[0]; propData.TextValue = null; propData.IntegerValue = null; return(true); }
private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueStorageType valueType) { //Get the INT ids stored for this property/drop down int[] ids = null; if (!propData.VarcharValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.VarcharValue); } else if (!propData.TextValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.TextValue); } else if (propData.IntegerValue.HasValue) { ids = new[] { propData.IntegerValue.Value }; } if (ids == null || ids.Length <= 0) { return(false); } // map ids to values var values = new List <Udi>(); var canConvert = true; foreach (var id in ids) { if (_nodeIdToKey.Value.TryGetValue(id, out var node)) { values.Add(Udi.Create(ObjectTypes.GetUdiType(node.NodeObjectType.Value), node.UniqueId)); } } if (!canConvert) { return(false); } propData.IntegerValue = null; if (valueType == ValueStorageType.Ntext) { propData.TextValue = String.Join(",", values); propData.VarcharValue = null; } else if (valueType == ValueStorageType.Nvarchar) { propData.TextValue = null; propData.VarcharValue = String.Join(",", values); } return(true); }
private string UpdateValueList(string propertyValue, ValueListConfiguration config, bool isMultiple) { var propData = new PropertyDataDto { VarcharValue = propertyValue }; if (UpdatePropertyDataDto(propData, config, isMultiple: isMultiple)) { return(propData.VarcharValue); } return(propertyValue); }
private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config) { //Get the INT ids stored for this property/drop down int[] ids = null; if (!propData.VarcharValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.VarcharValue); } else if (!propData.TextValue.IsNullOrWhiteSpace()) { ids = ConvertStringValues(propData.TextValue); } else if (propData.IntegerValue.HasValue) { ids = new[] { propData.IntegerValue.Value }; } //if there are INT ids, convert them to values based on the configured pre-values if (ids != null && ids.Length > 0) { //map the ids to values var vals = new List <string>(); var canConvert = true; foreach (var id in ids) { var val = config.Items.FirstOrDefault(x => x.Id == id); if (val != null) { vals.Add(val.Value); } else { Logger.Warn <DropDownPropertyEditorsMigration>( "Could not find associated data type configuration for stored Id {DataTypeId}", id); canConvert = false; } } if (canConvert) { propData.VarcharValue = string.Join(",", vals); propData.TextValue = null; propData.IntegerValue = null; return(true); } } return(false); }
private bool UpdateDropDownPropertyDataDto(PropertyDataDto propData, ValueListConfiguration config) { //Get the INT ids stored for this property/drop down var values = propData.VarcharValue.Split(new [] { "," }, StringSplitOptions.RemoveEmptyEntries); //if there are INT ids, convert them to values based on the configuration if (values == null || values.Length <= 0) { return(false); } //The radio button only supports selecting a single value, so if there are multiple for some insane reason we can only use the first propData.VarcharValue = JsonConvert.SerializeObject(values); propData.TextValue = null; propData.IntegerValue = null; return(true); }
private static void UpdateXmlTable(List <PropertyTypeDto> propertyTypes, PropertyDataDto data, List <ContentXmlDto> cmsContentXmlEntries, Database database) { //now we need to update the cmsContentXml table var propertyType = propertyTypes.SingleOrDefault(x => x.Id == data.PropertyTypeId); if (propertyType != null) { var xmlItem = cmsContentXmlEntries.SingleOrDefault(x => x.NodeId == data.NodeId); if (xmlItem != null) { var x = XElement.Parse(xmlItem.Xml); var prop = x.Element(propertyType.Alias); if (prop != null) { prop.ReplaceAll(new XCData(data.Text)); database.Update(xmlItem); } } } }
public void Issue8370Test() { // fixme maybe we need to create some content? // yes otherwise cannot get it to fail! var n = new NodeDto { Text = "text", CreateDate = DateTime.Now, Path = "-1", ParentId = -1, UniqueId = Guid.NewGuid() }; DatabaseContext.Database.Insert(n); var ct = new ContentTypeDto { Alias = "alias", NodeId = n.NodeId, Thumbnail = "thumb" }; DatabaseContext.Database.Insert(ct); n = new NodeDto { Text = "text", CreateDate = DateTime.Now, Path = "-1", ParentId = -1, UniqueId = Guid.NewGuid() }; DatabaseContext.Database.Insert(n); var dt = new DataTypeDto { PropertyEditorAlias = Constants.PropertyEditors.RelatedLinksAlias, DbType = "x", DataTypeId = n.NodeId }; DatabaseContext.Database.Insert(dt); var pt = new PropertyTypeDto { Alias = "alias", ContentTypeId = ct.NodeId, DataTypeId = dt.DataTypeId }; DatabaseContext.Database.Insert(pt); n = new NodeDto { Text = "text", CreateDate = DateTime.Now, Path = "-1", ParentId = -1, UniqueId = Guid.NewGuid() }; DatabaseContext.Database.Insert(n); var data = new PropertyDataDto { NodeId = n.NodeId, PropertyTypeId = pt.Id, Text = "text", VersionId = Guid.NewGuid() }; DatabaseContext.Database.Insert(data); data = new PropertyDataDto { NodeId = n.NodeId, PropertyTypeId = pt.Id, Text = "<root><node title=\"\" type=\"\" newwindow=\"\" link=\"\" /></root>", VersionId = Guid.NewGuid() }; DatabaseContext.Database.Insert(data); var migration = new UpdateRelatedLinksData(SqlSyntax, Logger); migration.UpdateRelatedLinksDataDo(DatabaseContext.Database); data = DatabaseContext.Database.Fetch <PropertyDataDto>("SELECT * FROM cmsPropertyData WHERE id=" + data.Id).FirstOrDefault(); Assert.IsNotNull(data); Debug.Print(data.Text); Assert.AreEqual("[{\"title\":\"\",\"caption\":\"\",\"link\":\"\",\"newWindow\":false,\"type\":\"external\",\"internal\":null,\"edit\":false,\"isInternal\":false}]", data.Text); }
protected IDictionary <int, PropertyCollection> GetPropertyCollection( Sql docSql, IEnumerable <DocumentDefinition> documentDefs) { if (documentDefs.Any() == false) { return(new Dictionary <int, PropertyCollection>()); } //we need to parse the original SQL statement and reduce the columns to just cmsContent.nodeId, cmsContentVersion.VersionId so that we can use // the statement to go get the property data for all of the items by using an inner join var parsedOriginalSql = "SELECT {0} " + docSql.SQL.Substring(docSql.SQL.IndexOf("FROM", StringComparison.Ordinal)); //now remove everything from an Orderby clause and beyond if (parsedOriginalSql.InvariantContains("ORDER BY ")) { parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal)); } var propSql = new Sql(@"SELECT cmsPropertyData.* FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyData.propertytypeid = cmsPropertyType.id INNER JOIN (" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId LEFT OUTER JOIN cmsDataTypePreValues ON cmsPropertyType.dataTypeId = cmsDataTypePreValues.datatypeNodeId", docSql.Arguments); var allPropertyData = Database.Fetch <PropertyDataDto>(propSql); //This is a lazy access call to get all prevalue data for the data types that make up all of these properties which we use // below if any property requires tag support var allPreValues = new Lazy <IEnumerable <DataTypePreValueDto> >(() => { var preValsSql = new Sql(@"SELECT a.id, a.value, a.sortorder, a.alias, a.datatypeNodeId FROM cmsDataTypePreValues a WHERE EXISTS( SELECT DISTINCT b.id as preValIdInner FROM cmsDataTypePreValues b INNER JOIN cmsPropertyType ON b.datatypeNodeId = cmsPropertyType.dataTypeId INNER JOIN (" + string.Format(parsedOriginalSql, "DISTINCT cmsContent.contentType") + @") as docData ON cmsPropertyType.contentTypeId = docData.contentType WHERE a.id = b.id)", docSql.Arguments); return(Database.Fetch <DataTypePreValueDto>(preValsSql)); }); var result = new Dictionary <int, PropertyCollection>(); var propertiesWithTagSupport = new Dictionary <string, SupportTagsAttribute>(); //iterate each definition grouped by it's content type - this will mean less property type iterations while building // up the property collections foreach (var compositionGroup in documentDefs.GroupBy(x => x.Composition)) { var compositionProperties = compositionGroup.Key.CompositionPropertyTypes.ToArray(); foreach (var def in compositionGroup) { var propertyDataDtos = allPropertyData.Where(x => x.NodeId == def.Id).Distinct(); var propertyFactory = new PropertyFactory(compositionProperties, def.Version, def.Id, def.CreateDate, def.VersionDate); var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray(); var newProperties = properties.Where(x => x.HasIdentity == false && x.PropertyType.HasIdentity); foreach (var property in newProperties) { var propertyDataDto = new PropertyDataDto { NodeId = def.Id, PropertyTypeId = property.PropertyTypeId, VersionId = def.Version }; int primaryKey = Convert.ToInt32(Database.Insert(propertyDataDto)); property.Version = def.Version; property.Id = primaryKey; } foreach (var property in properties) { //NOTE: The benchmarks run with and without the following code show very little change so this is not a perf bottleneck var editor = PropertyEditorResolver.Current.GetByAlias(property.PropertyType.PropertyEditorAlias); var tagSupport = propertiesWithTagSupport.ContainsKey(property.PropertyType.PropertyEditorAlias) ? propertiesWithTagSupport[property.PropertyType.PropertyEditorAlias] : TagExtractor.GetAttribute(editor); if (tagSupport != null) { //add to local cache so we don't need to reflect next time for this property editor alias propertiesWithTagSupport[property.PropertyType.PropertyEditorAlias] = tagSupport; //this property has tags, so we need to extract them and for that we need the prevals which we've already looked up var preValData = allPreValues.Value.Where(x => x.DataTypeNodeId == property.PropertyType.DataTypeDefinitionId) .Distinct() .ToArray(); var asDictionary = preValData.ToDictionary(x => x.Alias, x => new PreValue(x.Id, x.Value, x.SortOrder)); var preVals = new PreValueCollection(asDictionary); var contentPropData = new ContentPropertyData(property.Value, preVals, new Dictionary <string, object>()); TagExtractor.SetPropertyTags(property, contentPropData, property.Value, tagSupport); } } if (result.ContainsKey(def.Id)) { Logger.Warn <VersionableRepositoryBase <TId, TEntity> >("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name); } result[def.Id] = new PropertyCollection(properties); } } return(result); }