/// <inheritdoc/> public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } var urlPickerPropertyData = JsonConvert.DeserializeObject <IEnumerable <UrlPickerPropertyData> >(value); foreach (var urlPicker in urlPickerPropertyData) { // When we set the value we want to switch the Guid value of the contentId/mediaId to the integervalue // as this is what the UrlPicker uses to lookup it's content/media int contentId; if (TryGetId(urlPicker.TypeData.ContentId, UmbracoObjectTypes.Document, out contentId)) { urlPicker.TypeData.ContentId = contentId; } // The picker can have values set for both content and media even though only one of them is "active". // We still need to resolve the value for both settings. int mediaId; if (TryGetId(urlPicker.TypeData.MediaId, UmbracoObjectTypes.Media, out mediaId)) { urlPicker.TypeData.MediaId = mediaId; } } content.SetValue(alias, JsonConvert.SerializeObject(urlPickerPropertyData)); }
public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } var links = JsonConvert.DeserializeObject <JArray>(value); if (links != null) { foreach (var link in links) { GuidUdi udi; string url; // Only do processing on an item if the Id or the url is set if (TryParseJTokenAttr(link, "id", out udi)) { // Check the type of the link var nodeObjectType = link["isMedia"] != null ? UmbracoObjectTypes.Media : UmbracoObjectTypes.Document; // Get the Id corresponding to the Guid // it *should* succeed when deploying, due to dependencies management // nevertheless, assume it can fail, and then create an invalid localLink var idAttempt = _entityService.GetIdForKey(udi.Guid, nodeObjectType); if (idAttempt) { link["id"] = idAttempt.Success ? idAttempt.Result : 0; } } else if (TryParseJTokenAttr(link, "url", out url)) { // Check weather the url attribut of the link contains a udi, if so, replace it with the // path to the file, i.e. the regex replaces <udi> with /path/to/file var newUrl = MediaUdiSrcRegex.Replace(url, match => { var udiString = match.Groups["udi"].ToString(); GuidUdi foundUdi; if (GuidUdi.TryParse(udiString, out foundUdi) && foundUdi.EntityType == Constants.UdiEntityType.Media) { // (take care of nulls) var media = _mediaService.GetById(foundUdi.Guid); if (media != null) { return(media.GetUrl("umbracoFile", _logger)); } } return(string.Empty); }); link["url"] = newUrl; } } content.SetValue(alias, JsonConvert.SerializeObject(links)); } }
/// <inheritdoc/> public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } IEnumerable <UrlPickerPropertyData> urlPickerPropertyDatas; // If using an old version of the UrlPicker - data is serialized as a single object // Otherwise data is serialized as an array of objects, even if only one is selected. if (UrlPickerVersion.Value < UrlPickerVersionStoringArray) { var urlPickerPropertyData = JsonConvert.DeserializeObject <UrlPickerPropertyData>(value); urlPickerPropertyDatas = new List <UrlPickerPropertyData> { urlPickerPropertyData }; } else { urlPickerPropertyDatas = JsonConvert.DeserializeObject <IEnumerable <UrlPickerPropertyData> >(value).ToList(); } foreach (var urlPicker in urlPickerPropertyDatas) { // When we set the value we want to switch the Guid value of the contentId/mediaId to the integervalue // as this is what the UrlPicker uses to lookup it's content/media int contentId; if (TryGetId(urlPicker.TypeData.ContentId, UmbracoObjectTypes.Document, out contentId)) { urlPicker.TypeData.ContentId = contentId; } // The picker can have values set for both content and media even though only one of them is "active". // We still need to resolve the value for both settings. int mediaId; if (TryGetId(urlPicker.TypeData.MediaId, UmbracoObjectTypes.Media, out mediaId)) { urlPicker.TypeData.MediaId = mediaId; } } // If using an old version of the UrlPicker - data is serialized as a single object // Otherwise data is serialized as an array of objects, even if only one is selected. if (UrlPickerVersion.Value < UrlPickerVersionStoringArray) { content.SetValue(alias, JsonConvert.SerializeObject(urlPickerPropertyDatas.FirstOrDefault())); } else { content.SetValue(alias, JsonConvert.SerializeObject(urlPickerPropertyDatas)); } }
private async Task ImportFirstImageAsync(IContentBase postNode, BlogMLPost post) { var imageMimeTypes = new List <string> { "image/jpeg", "image/gif", "image/png" }; var attachment = post.Attachments.FirstOrDefault(p => imageMimeTypes.Contains(p.MimeType)); if (attachment == null) { return; } var imageSaved = false; if (!attachment.Content.IsNullOrWhiteSpace()) { //the image is base64 var bytes = Convert.FromBase64String(attachment.Content); using (var stream = new MemoryStream(bytes)) { postNode.SetValue(_contentTypeBaseServiceProvider, "postImage", attachment.Url.OriginalString, stream); imageSaved = true; } } else if (attachment.ExternalUri != null && attachment.ExternalUri.IsAbsoluteUri) { try { using (var client = new HttpClient()) { using (var stream = await client.GetStreamAsync(attachment.ExternalUri)) { postNode.SetValue(_contentTypeBaseServiceProvider, "postImage", Path.GetFileName(attachment.ExternalUri.AbsolutePath), stream); imageSaved = true; } } } catch (Exception exception) { _logger.Error <BlogMlImporter>(exception, "Exception retrieving {AttachmentUrl}; post {PostId}", attachment.Url, post.Id); } } if (imageSaved) { //this is a work around for the SetValue method to save a file, since it doesn't currently take into account the image cropper //which we are using so we need to fix that. var propType = postNode.Properties["postImage"].PropertyType; var cropperValue = CreateImageCropperValue(propType, postNode.GetValue("postImage"), _dataTypeService); postNode.SetValue("postImage", cropperValue); } }
public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } var relatedLinks = JsonConvert.DeserializeObject <JArray>(value); foreach (var relatedLink in relatedLinks) { //Get the value from the JSON object var isInternal = Convert.ToBoolean(relatedLink["isInternal"]); //We are only concerned about internal links if (!isInternal) { continue; } var relatedLinkValue = relatedLink["link"].ToString(); //Check if related links is stored as an int if (int.TryParse(relatedLinkValue, out var relatedLinkInt)) { //Update the JSON back to the int ids on this env relatedLink["link"] = relatedLinkInt; relatedLink["internal"] = relatedLinkInt; } else { //Get the UDI value in the JSON var pickedUdi = GuidUdi.Parse(relatedLinkValue); //Lets use entitiy sevice to get the int ID for this item on the new environment //Get the Id corresponding to the Guid //it *should* succeed when deploying, due to dependencies management //nevertheless, assume it can fail, and then create an invalid localLink var idAttempt = _entityService.GetIdForKey(pickedUdi.Guid, UmbracoObjectTypes.Document); //Update the JSON back to the int ids on this env relatedLink["link"] = idAttempt.Success ? idAttempt.Result : 0; relatedLink["internal"] = idAttempt.Success ? idAttempt.Result : 0; } } //Save the updated JSON with replaced UDIs for int IDs content.SetValue(alias, JsonConvert.SerializeObject(relatedLinks)); }
protected void SetPropertyOnContent(IContentBase content, PropertyRegistration property, object propertyValue) { object convertedValue; if (property.DataType.ConverterType != null) { object toConvert; var attr = property.Metadata.GetCodeFirstAttribute <ContentPropertyAttribute>(); if (attr != null && attr is IDataTypeRedirect) { toConvert = (attr as IDataTypeRedirect).GetOriginalDataTypeObject(propertyValue); } else { toConvert = propertyValue; } IDataTypeConverter converter = (IDataTypeConverter)Activator.CreateInstance(property.DataType.ConverterType); convertedValue = converter.Serialise(toConvert); } else if (!property.DataType.CodeFirstControlled && property.DataType.DbType == DatabaseType.None) { throw new CodeFirstException("Cannot persist PEVC-based properties or use events which attempt to persist PEVC-based properties. " + Environment.NewLine + "PEVCs only support retrieving a value from IPublishedContent & cannot persist a property back to IContent." + Environment.NewLine + "Property: " + property.Metadata.DeclaringType.FullName + "." + property.Name); } else { //No converter is given so we push the value back into umbraco as is (this will fail in many cases for PEVC properties) convertedValue = propertyValue; } content.SetValue(property.Alias, convertedValue); }
private async Task ImportFirstImageAsync(IContentBase postNode, BlogMLPost post) { var imageMimeTypes = new List <string> { "image/jpeg", "image/gif", "image/png" }; var attachment = post.Attachments.FirstOrDefault(p => imageMimeTypes.Contains(p.MimeType)); if (attachment == null) { return; } var path = attachment.Url.GetPath(); try { using (var client = new HttpClient()) { using (var stream = await client.GetStreamAsync(attachment.Url)) { postNode.SetValue("postImage", Path.GetFileName(path), stream); } } } catch (Exception exception) { LogHelper.Error <BlogMlImporter>($"Exception retrieving {attachment.Url}; post {post.Id}", exception); } }
private static void SetReservationStatus(IContentBase apartment, string valueName) { var dts = new DataTypeService(); var statusEditor = dts.GetAllDataTypeDefinitions().First(x => x.Name == "Status Rezerwacji"); var preValueId = dts.GetPreValuesCollectionByDataTypeId(statusEditor.Id).PreValuesAsDictionary.Where(d => d.Value.Value == valueName).Select(f => f.Value.Id).First(); apartment.SetValue("status", preValueId); }
private static void SetPropertyValue(IContentBase content, XmlNode uploadFieldConfigNode, string propertyAlias, string propertyValue) { XmlNode propertyNode = uploadFieldConfigNode.SelectSingleNode(propertyAlias); if (propertyNode != null && string.IsNullOrEmpty(propertyNode.FirstChild.Value) == false && content.HasProperty(propertyNode.FirstChild.Value)) { content.SetValue(propertyNode.FirstChild.Value, propertyValue); } }
/// <summary> /// Sets all invariant or variant property values safely while taking into account the variance settings on the content type/property type /// </summary> /// <param name="content">The content to set the values for</param> /// <param name="propertyAlias">The property alias to set the values for</param> /// <param name="propertyValueGetter">Callback to get the value to be set for the given culture</param> /// <remarks> /// This will only set property values for cultures that have been defined on the <see cref="IContentBase"/>, it will /// not set property values for cultures that don't yet exist on the content item. /// </remarks> public static void SetAllPropertyCultureValues( this IContentBase content, string propertyAlias, IContentTypeComposition contentType, Func <IContentBase, IContentTypeComposition, ContentCultureInfos, object> propertyValueGetter) { if (contentType is null) { throw new ArgumentNullException(nameof(contentType)); } if (content.ContentType.VariesByCulture()) { // iterate over any existing cultures defined on the content item foreach (var c in content.CultureInfos) { var propertyType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == propertyAlias); if (propertyType == null) { throw new InvalidOperationException($"No property type found by alias {propertyAlias}"); } var valueToSet = propertyValueGetter(content, contentType, c); if (valueToSet == null || (valueToSet is string propValAsString && string.IsNullOrWhiteSpace(propValAsString))) { continue; } content.SetValue(propertyAlias, valueToSet, propertyType.VariesByCulture() ? c.Culture : null); } } else { var propertyValue = propertyValueGetter(content, contentType, null); if (propertyValue == null || (propertyValue is string propValAsString && string.IsNullOrWhiteSpace(propValAsString))) { return; } content.SetValue(propertyAlias, propertyValue); } }
/// <summary> /// Sets a content property value using a deploy property. /// </summary> /// <param name="content">The content item.</param> /// <param name="alias">The property alias.</param> /// <param name="value">The deploy property value.</param> public void SetValue(IContentBase content, string alias, string value) { if (String.IsNullOrWhiteSpace(value)) { // Save empty value content.SetValue(alias, value); return; } if (!StringExtensions.DetectIsJson(value)) { // Skip invalid values return; } // Parse links and convert UDI back to local ID var rootLinks = ParseLinks(JArray.Parse(value), null, Direction.FromArtifact); content.SetValue(alias, rootLinks.ToString(Formatting.None)); }
public static void SetDropDownListValue(this IContentBase content, string aliasName, string dropValue) { try { var value = ((IContent)content).GetPropertyByAlias(aliasName).GetPreValue().GetPreValueIdByValue(dropValue); content.SetValue(aliasName, value); } catch { } }
public void SetValue(IContentBase content, string alias, string value) { // take the value if (string.IsNullOrWhiteSpace(value)) { return; } // deserialize it var model = JsonConvert.DeserializeObject <PropertyListValue>(value); if (model == null) { return; } // get the selected data-type (and ensure it exists) var dataType = _dataTypeService.GetDataTypeDefinitionById(model.DataTypeGuid); if (dataType == null) { throw new InvalidOperationException($"Could not resolve the data-type used by the Property List value for: {alias}"); } // make a property-type to use in a mocked Property // and get the value-connector needed to parse values (outside the loop, as it's the same for all iterations) var propertyType = new PropertyType(dataType, "mockPropertyListAlias"); var valueConnector = ValueConnectors.Get(propertyType); // loop through each value for (int i = 0; i < model.Values.Count; i++) { var item = model.Values[i]; var mockProperty = new Property(propertyType); var mockContent = new Content("mockContent", -1, new ContentType(-1), new PropertyCollection(new List <Property> { mockProperty })); // pass it to its own value-connector // NOTE: due to how ValueConnector.SetValue() works, we have to pass the mock item // through to the connector to have it do its work on parsing the value on the item itself. valueConnector.SetValue(mockContent, mockProperty.Alias, item?.ToString()); // get the value back and assign model.Values[i] = mockContent.GetValue(mockProperty.Alias); } // serialize the JSON values content.SetValue(alias, JObject.FromObject(model).ToString(Formatting.None)); }
public void SetValue(IContentBase content, string alias, string value) { // take the value if (string.IsNullOrWhiteSpace(value)) { return; } // deserialize it var items = JsonConvert.DeserializeObject <List <TupleValueItem> >(value); if (items == null || items.Count == 0) { return; } // loop through each value foreach (var item in items) { // get the selected data-type (and ensure it exists) var dataType = _dataTypeService.GetDataTypeDefinitionById(item.DataTypeGuid); if (dataType == null) { LogHelper.Warn <TupleValueConnector>($"Could not resolve the data-type used by the Tuple item for: {alias}, with GUID: {item.DataTypeGuid}"); continue; } // make a property-type to use in a mocked Property // and get the value-connector needed to parse values (outside the loop, as it's the same for all iterations) var propertyType = new PropertyType(dataType, "mockTupleAlias"); var valueConnector = ValueConnectors.Get(propertyType); var mockProperty = new Property(propertyType); var mockContent = new Content("mockContent", -1, new ContentType(-1), new PropertyCollection(new List <Property> { mockProperty })); // pass it to its own value-connector // NOTE: due to how ValueConnector.SetValue() works, we have to pass the mock item // through to the connector to have it do its work on parsing the value on the item itself. valueConnector.SetValue(mockContent, mockProperty.Alias, item.Value?.ToString()); // get the value back and assign item.Value = mockContent.GetValue(mockProperty.Alias); } // serialize the JSON values content.SetValue(alias, JArray.FromObject(items).ToString(Formatting.None)); }
/// <summary> /// second pass ID update in properties? /// </summary> /// <param name="node"></param> /// <param name="item"></param> public void DeserializeMappedIds(T baseItem, XElement node) { IContentBase item = (IContentBase)baseItem; var properties = node.Elements().Where(x => x.Attribute("isDoc") == null); foreach (var property in properties) { var propertyTypeAlias = property.Name.LocalName; if (item.HasProperty(propertyTypeAlias)) { var prop = item.Properties[propertyTypeAlias]; string newValue = GetImportIds(prop.PropertyType, GetImportXml(property)); LogHelper.Debug <Events>("#### BASE: Setting property: [{0}] to {1}", () => propertyTypeAlias, () => newValue); item.SetValue(propertyTypeAlias, newValue); } } }
/// <summary> /// Sets the value for a property type with the correct variance /// </summary> /// <remarks> /// Used to safely set a value for a property taking into account if the property type varies by culture/segment. /// If varying by culture it will assign the value to the default language only. /// If varying by segment it will assign the value to no segment. /// </remarks> public static void SetInvariantOrDefaultCultureValue( this IContentBase content, string propertyTypeAlias, object value, IContentTypeComposition contentType, ILocalizationService localizationService) { if (contentType is null) { throw new ArgumentNullException(nameof(contentType)); } var variesByCulture = VariesByCulture(propertyTypeAlias, contentType); content.SetValue( propertyTypeAlias, value, variesByCulture ? localizationService.GetDefaultLanguageIsoCode() : null); }
/// <summary> /// Sets the default value. /// </summary> /// <param name="content">The content to set default values for.</param> /// <param name="model">The model.</param> private static void SetDefaultValue(IContentBase content, PropertyType model) { if (!model.HasDefaultValue) { return; } var value = content.GetValue(model.Alias); if (value != null) { return; } if (!CanSetDefaultValue(model.Type, model.DefaultValue)) { return; } content.SetValue(model.Alias, model.DefaultValue); }
/// <summary> /// Sets a content property value using a deploy property. /// </summary> /// <param name="content">The content item.</param> /// <param name="alias">The property alias.</param> /// <param name="value">The deploy property value.</param> public void SetValue(IContentBase content, string alias, string value) { // parse the value - checking the format - CSV, XML or JSON SaveFormat format; var items = ParseValue(value, out format); var result = new List <KeyValuePair <string, string> >(); // loop over the values foreach (var item in items) { GuidUdi guidUdi; if (GuidUdi.TryParse(item.Key, out guidUdi) && guidUdi.Guid != Guid.Empty) { // if an UDI, attempt to get the INT var nodeId = GetIntId(guidUdi.Guid); if (nodeId > 0) { result.Add(new KeyValuePair <string, string>(nodeId.ToString(), item.Value)); } else { // the value isn't a node ID, assume it's "just a string" result.Add(item); } } else { // the value isn't a UDI, assume it's "just a string" result.Add(item); } } // re-assemble the values into the correct format - CSV, XML, JSON, (whatevs) content.SetValue(alias, SerializeValue(result, format)); }
private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string filename, Stream fileStream) { var property = content.Properties.FirstOrDefault(x => x.Alias == propertyTypeAlias); if (property == null) return; //TODO: ALl of this naming logic needs to be put into the ImageHelper and then we need to change FileUploadPropertyValueEditor to do the same! var numberedFolder = MediaSubfolderCounter.Current.Increment(); var fileName = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), filename) : numberedFolder + "-" + filename; var extension = Path.GetExtension(filename).Substring(1).ToLowerInvariant(); //the file size is the length of the stream in bytes var fileSize = fileStream.Length; var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>(); fs.AddFile(fileName, fileStream); //Check if file supports resizing and create thumbnails var supportsResizing = UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.InvariantContains(extension); //the config section used to auto-fill properties IImagingAutoFillUploadField uploadFieldConfigNode = null; //Check for auto fill of additional properties if (UmbracoConfig.For.UmbracoSettings().Content.ImageAutoFillProperties != null) { uploadFieldConfigNode = UmbracoConfig.For.UmbracoSettings().Content.ImageAutoFillProperties .FirstOrDefault(x => x.Alias == propertyTypeAlias); } if (supportsResizing) { //get the original image from the original stream if (fileStream.CanSeek) fileStream.Seek(0, 0); using (var originalImage = Image.FromStream(fileStream)) { var additionalSizes = new List<int>(); //Look up Prevalues for this upload datatype - if it is an upload datatype - get additional configured sizes if (property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias) { //Get Prevalues by the DataType's Id: property.PropertyType.DataTypeId var values = ApplicationContext.Current.Services.DataTypeService.GetPreValuesByDataTypeId(property.PropertyType.DataTypeDefinitionId); var thumbnailSizes = values.FirstOrDefault(); //Additional thumbnails configured as prevalues on the DataType if (thumbnailSizes != null) { var sep = (thumbnailSizes.Contains("") == false && thumbnailSizes.Contains(",")) ? ',' : ';'; foreach (var thumb in thumbnailSizes.Split(sep)) { int thumbSize; if (thumb != "" && int.TryParse(thumb, out thumbSize)) { additionalSizes.Add(thumbSize); } } } } ImageHelper.GenerateMediaThumbnails(fs, fileName, extension, originalImage, additionalSizes); //while the image is still open, we'll check if we need to auto-populate the image properties if (uploadFieldConfigNode != null) { content.SetValue(uploadFieldConfigNode.WidthFieldAlias, originalImage.Width.ToString(CultureInfo.InvariantCulture)); content.SetValue(uploadFieldConfigNode.HeightFieldAlias, originalImage.Height.ToString(CultureInfo.InvariantCulture)); } } } //if auto-fill is true, then fill the remaining, non-image properties if (uploadFieldConfigNode != null) { content.SetValue(uploadFieldConfigNode.LengthFieldAlias, fileSize.ToString(CultureInfo.InvariantCulture)); content.SetValue(uploadFieldConfigNode.ExtensionFieldAlias, extension); } //Set the value of the property to that of the uploaded file's url property.Value = fs.GetUrl(fileName); }
/// <summary> /// Sets the posted file value of a property. /// </summary> public static void SetValue(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, HttpPostedFileBase postedFile, string culture = null, string segment = null) { content.SetValue(contentTypeBaseServiceProvider, propertyTypeAlias, postedFile.FileName, postedFile.InputStream, culture, segment); }
public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } if (value.DetectIsJson() == false) { return; } var property = content.Properties[alias]; if (property == null) { throw new NullReferenceException($"Property not found: '{alias}'."); } var prevalues = _dataTypeService.GetPreValuesCollectionByDataTypeId(property.PropertyType.DataTypeDefinitionId).FormatAsDictionary(); PreValue prevalue = null; //Fetch the Prevalues for the current Property's DataType (if its an 'Archetype config') if (!prevalues.TryGetValue("archetypeconfig", out prevalue) && !prevalues.TryGetValue("archetypeConfig", out prevalue)) { throw new InvalidOperationException("Could not find Archetype configuration."); } var archetypePreValue = prevalue == null ? null : JsonConvert.DeserializeObject <ArchetypePreValue>(prevalue.Value); RetrieveAdditionalProperties(ref archetypePreValue); var archetype = JsonConvert.DeserializeObject <ArchetypeModel>(value); if (archetype == null) { throw new InvalidOperationException("Could not parse Archetype value."); } RetrieveAdditionalProperties(ref archetype, archetypePreValue); var properties = archetype.Fieldsets.SelectMany(x => x.Properties); foreach (var archetypeProperty in properties) { if (archetypeProperty.Value == null || string.IsNullOrEmpty(archetypeProperty.DataTypeGuid)) { continue; } // get the data type of the property var dataType = _dataTypeService.GetDataTypeDefinitionById(Guid.Parse(archetypeProperty.DataTypeGuid)); if (dataType == null) { throw new ArgumentNullException( $"Unable to find the data type for editor '{archetypeProperty.PropertyEditorAlias}' ({archetypeProperty.DataTypeGuid}) referenced by '{property.Alias}'."); } // try to convert the value with the macro parser - this is mainly for legacy editors var archetypeValue = _macroParser.ReplaceAttributeValue(archetypeProperty.Value.ToString(), dataType.PropertyEditorAlias, null, Direction.FromArtifact); Udi udi; // test if the macroparser converted the value to an Udi if (Udi.TryParse(archetypeValue, out udi)) { archetypeProperty.Value = archetypeValue; continue; } // if the macro parser didn't convert the value then try to find a value connector that can and convert it var propertyType = new PropertyType(dataType.PropertyEditorAlias, dataType.DatabaseType, "mockPropertyTypeAlias"); propertyType.DataTypeDefinitionId = dataType.Id; var propValueConnector = ValueConnectors.Get(propertyType); var mockProperty = new Property(propertyType); var mockContent = new Content("mockContent", -1, new ContentType(-1), new PropertyCollection(new List <Property> { mockProperty })); propValueConnector.SetValue(mockContent, mockProperty.Alias, archetypeProperty.Value.ToString()); archetypeProperty.Value = mockContent.GetValue(mockProperty.Alias); } value = archetype.SerializeForPersistence(); content.SetValue(alias, value); }
/// <summary> /// Sets a content property value using a deploy property. /// </summary> /// <param name="content">The content item.</param> /// <param name="alias">The property alias.</param> /// <param name="value">The deploy property value.</param> /// <remarks> /// This is a bit tricky because for each cell of nested content we need to pass the value of it to it's related /// IValueConnector because each cell is essentially a Property Type - though a fake one. /// So to do this we have to create a fake content item for the underlying IValueConnector to set it's value on and /// then we can extract that value from it to put on the main serialized object to set on the real IContentBase item. /// </remarks> public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } if (value.DetectIsJson() == false) { return; } var nestedContent = JsonConvert.DeserializeObject <NestedContentValue[]>(value); if (nestedContent == null) { return; } var allContentTypes = nestedContent.Select(x => x.ContentTypeAlias) .Distinct() .ToDictionary(a => a, a => _contentTypeService.GetContentType(a)); //Ensure all of these content types are found if (allContentTypes.Values.Any(contentType => contentType == null)) { throw new InvalidOperationException($"Could not resolve these content types for the Nested Content property: {string.Join(",", allContentTypes.Where(x => x.Value == null).Select(x => x.Key))}"); } var mocks = new Dictionary <IContentType, IContent>(); foreach (var row in nestedContent) { var contentType = allContentTypes[row.ContentTypeAlias]; // note // the way we do it here, doing content.SetValue() several time on the same content, reduces // allocations and should be ok because SetValue does not care about the previous value - would // be different for the overloads that manage eg files for uploads (not sure how NestedContent // deals with them really) // we need a fake content instance to pass in to the value connector, since the value connector // wants to SetValue on an object - then we can extract the value back from that object to set // it correctly on the real instance IContent mockContent; if (!mocks.TryGetValue(contentType, out mockContent)) { mockContent = mocks[contentType] = new Content("NC_" + Guid.NewGuid(), -1, contentType); } foreach (var key in row.PropertyValues.Keys.ToArray()) { // key is a system property that is added by NestedContent in Core v7.7 // see note in NestedContentValue - leave it unchanged if (key == "key") { continue; } var propertyType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == key); if (propertyType == null) { LogHelper.Debug <NestedContentValueConnector>($"No Property Type found with alias {key} on Content Type {contentType.Alias}"); continue; } // throws if not found - no need for a null check var propValueConnector = ValueConnectors.Get(propertyType); var rowValue = row.PropertyValues[key]; if (rowValue != null) { propValueConnector.SetValue(mockContent, propertyType.Alias, rowValue.ToString()); var convertedValue = mockContent.GetValue(propertyType.Alias); if (convertedValue == null) { row.PropertyValues[key] = null; } // integers needs to be converted into strings else if (convertedValue is int) { row.PropertyValues[key] = convertedValue.ToString(); } else { // test if the value is a json object (thus could be a nested complex editor) // if that's the case we'll need to add it as a json object instead of string to avoid it being escaped JToken jtokenValue = convertedValue.ToString().DetectIsJson() ? JToken.Parse(convertedValue.ToString()) : null; if (jtokenValue != null) { row.PropertyValues[key] = jtokenValue; } else { row.PropertyValues[key] = convertedValue; } } } else { row.PropertyValues[key] = rowValue; } } } // NestedContent does not use formatting when serializing JSON values if (nestedContent.Length == 1) { value = JObject.FromObject(nestedContent.FirstOrDefault()).ToString(Formatting.None); } else { value = JArray.FromObject(nestedContent).ToString(Formatting.None); } content.SetValue(alias, value); }
public void SetValue(IContentBase content, string alias, string value) { //Save the JSON on the env we are deploying to //We don't need to swap UDIs out back for int's so a simple setValue is all we need content.SetValue(alias, value); }
private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string filename, Stream fileStream) { var property = content.Properties.FirstOrDefault(x => x.Alias == propertyTypeAlias); if (property == null) { return; } //TODO: ALl of this naming logic needs to be put into the ImageHelper and then we need to change FileUploadPropertyValueEditor to do the same! var numberedFolder = MediaSubfolderCounter.Current.Increment(); var fileName = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? Path.Combine(numberedFolder.ToString(CultureInfo.InvariantCulture), filename) : numberedFolder + "-" + filename; var extension = Path.GetExtension(filename).Substring(1).ToLowerInvariant(); //the file size is the length of the stream in bytes var fileSize = fileStream.Length; var fs = FileSystemProviderManager.Current.GetFileSystemProvider <MediaFileSystem>(); fs.AddFile(fileName, fileStream); //Check if file supports resizing and create thumbnails var supportsResizing = UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes.InvariantContains(extension); //the config section used to auto-fill properties IImagingAutoFillUploadField uploadFieldConfigNode = null; //Check for auto fill of additional properties if (UmbracoConfig.For.UmbracoSettings().Content.ImageAutoFillProperties != null) { uploadFieldConfigNode = UmbracoConfig.For.UmbracoSettings().Content.ImageAutoFillProperties .FirstOrDefault(x => x.Alias == propertyTypeAlias); } if (supportsResizing) { //get the original image from the original stream if (fileStream.CanSeek) { fileStream.Seek(0, 0); } using (var originalImage = Image.FromStream(fileStream)) { var additionalSizes = new List <int>(); //Look up Prevalues for this upload datatype - if it is an upload datatype - get additional configured sizes if (property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias) { //Get Prevalues by the DataType's Id: property.PropertyType.DataTypeId var values = ApplicationContext.Current.Services.DataTypeService.GetPreValuesByDataTypeId(property.PropertyType.DataTypeDefinitionId); var thumbnailSizes = values.FirstOrDefault(); //Additional thumbnails configured as prevalues on the DataType if (thumbnailSizes != null) { foreach (var thumb in thumbnailSizes.Split(new[] { ";", "," }, StringSplitOptions.RemoveEmptyEntries)) { int thumbSize; if (thumb != "" && int.TryParse(thumb, out thumbSize)) { additionalSizes.Add(thumbSize); } } } } ImageHelper.GenerateMediaThumbnails(fs, fileName, extension, originalImage, additionalSizes); //while the image is still open, we'll check if we need to auto-populate the image properties if (uploadFieldConfigNode != null) { content.SetValue(uploadFieldConfigNode.WidthFieldAlias, originalImage.Width.ToString(CultureInfo.InvariantCulture)); content.SetValue(uploadFieldConfigNode.HeightFieldAlias, originalImage.Height.ToString(CultureInfo.InvariantCulture)); } } } //if auto-fill is true, then fill the remaining, non-image properties if (uploadFieldConfigNode != null) { content.SetValue(uploadFieldConfigNode.LengthFieldAlias, fileSize.ToString(CultureInfo.InvariantCulture)); content.SetValue(uploadFieldConfigNode.ExtensionFieldAlias, extension); } //Set the value of the property to that of the uploaded file's url property.Value = fs.GetUrl(fileName); }
/// <summary> /// Sets a content property value using a deploy property. /// </summary> /// <param name="content">The content item.</param> /// <param name="alias">The property alias.</param> /// <param name="value">The deploy property value.</param> /// <remarks> /// This will loop through all the values stored inside the Vorto property, using the IValueConnector to parse each value. /// Due to how the ValueConnectors set the value, we have to create mocked content items and assign the value to it. /// Then the mock item is passed to the ValueConnector, matching the property type being wrapped by Vorto and the /// ValueConnector will parse the value. /// When the ValueConnector has done its work, the parsed value is extracted from the mock content and then assigned back /// to the original field inside the Vorto value object instead. /// </remarks> public void SetValue(IContentBase content, string alias, string value) { // if there's an empty value we don't need to do more work if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } // fail fast if this isn't JSON if (value.DetectIsJson() == false) { return; } // try parsing this as a Vorto value var vortoValue = JsonConvert.DeserializeObject <VortoValue>(value); if (vortoValue == null) { return; } // getting the wrapped datatype via the Vorto datatype var vortoDataType = _dataTypeService.GetDataTypeDefinitionById(Guid.Parse(vortoValue.DtdGuid)); var vortoDataTypePrevalueJson = _dataTypeService.GetPreValuesCollectionByDataTypeId(vortoDataType.Id).FormatAsDictionary().FirstOrDefault(x => x.Key == "dataType").Value.Value; var vortoDataTypePrevalue = JsonConvert.DeserializeObject <VortoDatatypePrevalue>(vortoDataTypePrevalueJson); var wrappedDataType = _dataTypeService.GetDataTypeDefinitionById(vortoDataTypePrevalue.Guid); // ensure the wrapped datatype is found if (wrappedDataType == null) { throw new InvalidOperationException($"Could not resolve the datatype used inside the Vorto property: {alias}"); } var propertyType = new PropertyType(wrappedDataType, "mockPropertyType"); var valueConnector = ValueConnectors.Get(propertyType); // iterate values for each language foreach (var languageKey in vortoValue.Values.ValuePairs.Keys.ToArray()) { var val = vortoValue.Values.ValuePairs[languageKey]; var mockProperty = new Property(propertyType, val); var mockContent = new Content("mockContent", -1, new ContentType(-1), new PropertyCollection(new List <Property> { mockProperty })); // due to how ValueConnector.SetValue() works, we have to pass the mock item through the connector to have it do its // work on parsing the value on the item itself. valueConnector.SetValue(mockContent, mockProperty.Alias, val.ToString()); // we then extract the converted value from the mock item so we can assign it to the inner value object inside the // actual Vorto item's value pair for this specific language. var convertedValue = mockContent.GetValue(mockProperty.Alias); var jtokenValue = convertedValue != null && convertedValue.ToString().DetectIsJson() ? JToken.Parse(convertedValue.ToString()) : null; if (jtokenValue != null) { convertedValue = jtokenValue; } else if (convertedValue != null) { convertedValue = convertedValue.ToString(); } vortoValue.Values.ValuePairs[languageKey] = convertedValue; } // Vorto does not use formatting when serializing JSON values value = JObject.FromObject(vortoValue).ToString(Formatting.None); content.SetValue(alias, value); }
/// <summary> /// Sets a content property value using a deploy property. /// </summary> /// <param name="content">The content item.</param> /// <param name="alias">The property alias.</param> /// <param name="value">The deploy property value.</param> /// <remarks> /// This is a bit tricky because for each row of inner content we need to pass the value of it to it's related /// IValueConnector because each row is essentially a Property Type - though a fake one. /// So to do this we have to create a fake content item for the underlying IValueConnector to set it's value on and /// then we can extract that value from it to put on the main serialized object to set on the real IContentBase item. /// </remarks> public void SetValue(IContentBase content, string alias, string value) { if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } if (value.DetectIsJson() == false) { return; } var innerContent = JsonConvert.DeserializeObject <InnerContentValue[]>(value); if (innerContent == null) { return; } foreach (var innerContentItem in innerContent) { IContentType contentType = null; if (innerContentItem.IcContentTypeGuid.HasValue) { contentType = _contentTypeService.GetContentType(innerContentItem.IcContentTypeGuid.Value); } if (contentType == null) { contentType = _contentTypeService.GetContentType(innerContentItem.IcContentTypeAlias); } if (contentType == null) { throw new InvalidOperationException($"Could not resolve these content types for the Inner Content property with key: {innerContentItem.Key}, and name: {innerContentItem.Name}"); } var mocks = new Dictionary <IContentType, IContent>(); // note // the way we do it here, doing content.SetValue() several time on the same content, reduces // allocations and should be ok because SetValue does not care about the previous value - would // be different for the overloads that manage eg files for uploads (not sure how NestedContent // deals with them really) // we need a fake content instance to pass in to the value connector, since the value connector // wants to SetValue on an object - then we can extract the value back from that object to set // it correctly on the real instance IContent mockContent; if (!mocks.TryGetValue(contentType, out mockContent)) { mockContent = mocks[contentType] = new Content("IC_" + Guid.NewGuid(), -1, contentType); } if (innerContentItem.PropertyValues != null) { foreach (var key in innerContentItem.PropertyValues.Keys.ToArray()) { var propertyType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == key); if (propertyType == null) { LogHelper.Debug <InnerContentConnector>($"No Property Type found with alias {key} on Content Type {contentType.Alias}"); continue; } // throws if not found - no need for a null check var propValueConnector = ValueConnectors.Get(propertyType); var rowValue = innerContentItem.PropertyValues[key]; if (rowValue != null) { propValueConnector.SetValue(mockContent, propertyType.Alias, rowValue.ToString()); var convertedValue = mockContent.GetValue(propertyType.Alias); // integers needs to be converted into strings if (convertedValue is int) { innerContentItem.PropertyValues[key] = convertedValue.ToString(); } else { // test if the value is a json object (thus could be a nested complex editor) // if that's the case we'll need to add it as a json object instead of string to avoid it being escaped JToken jtokenValue; if (TryParseJToken(convertedValue, out jtokenValue)) { innerContentItem.PropertyValues[key] = jtokenValue; } else { innerContentItem.PropertyValues[key] = convertedValue; } } } else { innerContentItem.PropertyValues[key] = rowValue; } } } } // InnerContent does not use formatting when serializing JSON values value = JArray.FromObject(innerContent).ToString(Formatting.None); content.SetValue(alias, value); }
/// <summary> /// Sets a content property value using a deploy property. /// </summary> /// <param name="content">The content item.</param> /// <param name="alias">The property alias.</param> /// <param name="value">The deploy property value.</param> /// <remarks> /// This will loop through all the values stored inside the Vorto property, using the IValueConnector to parse each value. /// Due to how the ValueConnectors set the value, we have to create mocked content items and assign the value to it. /// Then the mock item is passed to the ValueConnector, matching the property type being wrapped by Vorto and the /// ValueConnector will parse the value. /// When the ValueConnector has done its work, the parsed value is extracted from the mock content and then assigned back /// to the original field inside the Vorto value object instead. /// </remarks> public void SetValue(IContentBase content, string alias, string value) { // if there's an empty value we don't need to do more work if (string.IsNullOrWhiteSpace(value)) { content.SetValue(alias, value); return; } // fail fast if this isn't JSON if (value.DetectIsJson() == false) { return; } // try parsing this as a Vorto value var vortoValue = JsonConvert.DeserializeObject <VortoValue>(value); if (vortoValue == null) { return; } // old versions of Vorto doesn't seem to store a DtdGuid - in those cases we just deploy the value as it is without any further handling. if (string.IsNullOrWhiteSpace(vortoValue.DtdGuid)) { LogHelper.Debug <VortoValueConnector>($"No datatype definition defined inside the Vorto property: {alias} - are you using an old version of Vorto? - data value will be deployed as it is."); content.SetValue(alias, value); return; } // getting the wrapped datatype via the Vorto datatype var vortoDataType = _dataTypeService.GetDataTypeDefinitionById(Guid.Parse(vortoValue.DtdGuid)); var vortoDataTypePrevalueJson = _dataTypeService.GetPreValuesCollectionByDataTypeId(vortoDataType.Id).FormatAsDictionary().FirstOrDefault(x => x.Key == "dataType").Value.Value; var vortoDataTypePrevalue = JsonConvert.DeserializeObject <VortoDatatypePrevalue>(vortoDataTypePrevalueJson); var wrappedDataType = _dataTypeService.GetDataTypeDefinitionById(vortoDataTypePrevalue.Guid); // ensure the wrapped datatype is found if (wrappedDataType == null) { throw new InvalidOperationException($"Could not resolve the datatype used inside the Vorto property: {alias}"); } var propertyType = new PropertyType(wrappedDataType, MockPropertyTypeAlias); var valueConnector = ValueConnectors.Get(propertyType); // iterate values for each language foreach (var languageKey in vortoValue.Values.ValuePairs.Keys.ToArray()) { var val = vortoValue.Values.ValuePairs[languageKey]; var mockProperty = new Property(propertyType); var mockContent = new Content("mockContent", -1, new ContentType(-1), new PropertyCollection(new List <Property> { mockProperty })); // due to how ValueConnector.SetValue() works, we have to pass the mock item through the connector to have it do its // work on parsing the value on the item itself. valueConnector.SetValue(mockContent, mockProperty.Alias, val?.ToString()); // get the value back and assign var convertedValue = mockContent.GetValue(mockProperty.Alias); vortoValue.Values.ValuePairs[languageKey] = convertedValue; } // Vorto does not use formatting when serializing JSON values value = JObject.FromObject(vortoValue).ToString(Formatting.None); content.SetValue(alias, value); }