/// <summary> /// Constructor specifies the defaults and sets the ContentPropertyData being used to set the tag values which /// can be used to dynamically adjust the tags definition for this property. /// </summary> /// <param name="propertySaving"></param> /// <param name="tagsAttribute"></param> protected TagPropertyDefinition(ContentPropertyData propertySaving, SupportTagsAttribute tagsAttribute) { PropertySaving = propertySaving; TagsAttribute = tagsAttribute; Delimiter = tagsAttribute.Delimiter; ReplaceTags = tagsAttribute.ReplaceTags; TagGroup = tagsAttribute.TagGroup; }
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { if (editorValue.Value == null || string.IsNullOrEmpty(editorValue.Value.ToString())) { return ""; } return SecurityHelper.Encrypt(editorValue.Value.ToString(), SecurityHelper.GetKey()); }
/// <summary> /// Sets the tag values on the content property based on the property editor's tags attribute /// </summary> /// <param name="content"></param> /// <param name="property"></param> /// <param name="propertyData"></param> /// <param name="convertedPropertyValue"></param> /// <param name="attribute"></param> public static void SetPropertyTags(IContentBase content, Property property, ContentPropertyData propertyData, object convertedPropertyValue, SupportTagsAttribute attribute) { //check for a custom definition if (attribute.TagPropertyDefinitionType != null) { //try to create it TagPropertyDefinition def; try { def = (TagPropertyDefinition) Activator.CreateInstance(attribute.TagPropertyDefinitionType, propertyData, attribute); } catch (Exception ex) { LogHelper.Error<TagExtractor>("Could not create custom " + attribute.TagPropertyDefinitionType + " tag definition", ex); throw; } SetPropertyTags(content, property, convertedPropertyValue, def.Delimiter, def.ReplaceTags, def.TagGroup, attribute.ValueType); } else { SetPropertyTags(content, property, convertedPropertyValue, attribute.Delimiter, attribute.ReplaceTags, attribute.TagGroup, attribute.ValueType); } }
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { if (editorValue.Value == null) return string.Empty; try { var value = JsonConvert.DeserializeObject<VortoValue>(editorValue.Value.ToString()); var dtd = VortoHelper.GetTargetDataTypeDefinition(value.DtdGuid); var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id); var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias); var keys = value.Values.Keys.ToArray(); foreach (var key in keys) { var propData = new ContentPropertyData(value.Values[key], preValues, new Dictionary<string, object>()); var newValue = propEditor.ValueEditor.ConvertEditorToDb(propData, value.Values[key]); value.Values[key] = (newValue == null) ? null : JToken.FromObject(newValue); } return JsonConvert.SerializeObject(value); } catch (Exception ex) { LogHelper.Error<VortoPropertyValueEditor>("Error converting DB value to Editor", ex); } return base.ConvertEditorToDb(editorValue, currentValue); }
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { if(editorValue.Value == null || editorValue.Value.ToString() == "") return string.Empty; // attempt to deserialize the current property value as an Archetype var currentArchetype = currentValue != null ? ArchetypeHelper.Instance.DeserializeJsonToArchetype(currentValue.ToString(), editorValue.PreValues) : null; var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(editorValue.Value.ToString(), editorValue.PreValues); // get all files uploaded via the file manager (if any) var uploadedFiles = editorValue.AdditionalData.ContainsKey("files") ? editorValue.AdditionalData["files"] as IEnumerable<ContentItemFile> : null; foreach (var fieldset in archetype.Fieldsets) { // assign an id to the fieldset if it has none (e.g. newly created fieldset) fieldset.Id = fieldset.Id == Guid.Empty ? Guid.NewGuid() : fieldset.Id; // find the corresponding fieldset in the current Archetype value (if any) var currentFieldset = currentArchetype != null ? currentArchetype.Fieldsets.FirstOrDefault(f => f.Id == fieldset.Id) : null; foreach (var propDef in fieldset.Properties) { try { // find the corresponding property in the current Archetype value (if any) var currentProperty = currentFieldset != null ? currentFieldset.Properties.FirstOrDefault(p => p.Alias == propDef.Alias) : null; var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid)); var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id); var additionalData = new Dictionary<string, object>(); // figure out if we need to pass a files collection in the additional data to the property value editor if(uploadedFiles != null) { if(dtd.PropertyEditorAlias == Constants.PropertyEditorAlias) { // it's a nested Archetype - just pass all uploaded files to the value editor additionalData["files"] = uploadedFiles.ToList(); } else if (propDef.EditorState != null && propDef.EditorState.FileNames != null && propDef.EditorState.FileNames.Any()) { // pass the uploaded files that belongs to this property (if any) to the value editor var propertyFiles = propDef.EditorState.FileNames.Select(f => uploadedFiles.FirstOrDefault(u => u.FileName == f)).Where(f => f != null).ToList(); if(propertyFiles.Any()) { additionalData["files"] = propertyFiles; } } } var propData = new ContentPropertyData(propDef.Value, preValues, additionalData); var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias); // make sure to send the current property value (if any) to the PE ValueEditor propDef.Value = propEditor.ValueEditor.ConvertEditorToDb(propData, currentProperty != null ? currentProperty.Value : null); } catch (Exception ex) { LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex); } } } return archetype.SerializeForPersistence(); }
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { if (editorValue.Value == null || editorValue.Value.ToString() == "") return string.Empty; //LogHelper.Info<ArchetypeHelper>(editorValue.Value.ToString()); var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(editorValue.Value.ToString(), editorValue.PreValues); foreach (var fieldset in archetype.Fieldsets) { foreach (var propDef in fieldset.Properties) { try { var dtd = ApplicationContext.Current.Services.DataTypeService.GetDataTypeDefinitionById(Guid.Parse(propDef.DataTypeGuid)); var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id); var propData = new ContentPropertyData(propDef.Value, preValues, new Dictionary<string, object>()); var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias); propDef.Value = propEditor.ValueEditor.ConvertEditorToDb(propData, propDef.Value); } catch (Exception ex) { LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex); } } } return archetype.SerializeForPersistence(); }
protected object ConvertEditorToDb_Fake(string propEditorAlias, object value) { // Lookup the property editor var fakePropEditor = PropertyEditorResolver.Current.GetByAlias(propEditorAlias); // Create a fake content property data object (note, we don't have a prevalue, so passing in null) var fakeContentPropData = new ContentPropertyData(value, null, new Dictionary<string, object>()); // Get the property editor to do it's conversion var fakeNewValue = fakePropEditor.ValueEditor.ConvertEditorToDb(fakeContentPropData, value); // Store the value back return fakeNewValue == null ? null : fakeNewValue.ToString(); }
protected object ConvertEditorToDb_DocType(string docTypeAlias, object value) { var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(docTypeAlias); // Loop through doc type properties var propValues = ((JObject)value); var propValueKeys = propValues.Properties().Select(x => x.Name).ToArray(); if (contentType != null && contentType.PropertyTypes != null) { foreach (var propKey in propValueKeys) { // Fetch the current property type var propType = contentType.PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propKey)); if (propType == null) { if (propKey != "name") { // Property missing so just remove the value propValues[propKey] = null; } } else { // Fetch the property types prevalue var propPreValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId( propType.DataTypeDefinitionId); // Lookup the property editor var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); // Create a fake content property data object var contentPropData = new ContentPropertyData( propValues[propKey] == null ? null : propValues[propKey].ToString(), propPreValues, new Dictionary<string, object>()); // Get the property editor to do it's conversion var newValue = propEditor.ValueEditor.ConvertEditorToDb(contentPropData, propValues[propKey]); // Store the value back propValues[propKey] = (newValue == null) ? null : JToken.FromObject(newValue); } } } return propValues; }
/// <summary> /// A method to deserialize the value that has been saved by an editor /// to an object to be stored in the database. /// </summary> /// <param name="contentType"> /// The content type. /// </param> /// <param name="dcv"> /// The detached content value. /// </param> /// <param name="additionalData"> /// The additional Data. /// </param> /// <returns> /// The converted value. /// </returns> private KeyValuePair<string, string> ConvertEditorToDb(IContentType contentType, KeyValuePair<string, string> dcv, IDictionary<string, object> additionalData) { var propType = contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Alias == dcv.Key); if (propType == null) { return dcv; } // Lookup the property editor var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); if (propEditor.ValueEditor.IsReadOnly) return dcv; // Fetch the property types prevalue var propPreValues = _dataTypeService.GetPreValuesCollectionByDataTypeId(propType.DataTypeDefinitionId); var rawValue = JsonConvert.DeserializeObject(dcv.Value.Trim()); //// Create a fake content property data object if (additionalData == null) additionalData = new Dictionary<string, object>(); var contentPropData = new ContentPropertyData(rawValue, propPreValues, additionalData); try { // Get the property editor to do it's conversion var newValue = propEditor.ValueEditor.ConvertEditorToDb(contentPropData, null); // Store the value back var value = newValue == null ? string.Empty : JsonHelper.IsJsonObject(newValue) ? newValue.ToString() : JsonConvert.SerializeObject(newValue); return new KeyValuePair<string, string>(dcv.Key, value); } catch (Exception ex) { var logData = MultiLogger.GetBaseLoggingData(); logData.AddCategory("ValueEditor"); MultiLogHelper.WarnWithException<DetachedValuesConverter>( "Failed to convert property value for Database", ex, logData); return dcv; } }
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { if (editorValue.Value == null || string.IsNullOrWhiteSpace(editorValue.Value.ToString())) return null; var value = JsonConvert.DeserializeObject<MortarValue>(editorValue.Value.ToString()); if (value == null) return null; foreach (var key in value.Keys) { var rowOptionsDocTypeAlias = MortarHelper.GetRowOptionsDocType(editorValue.PreValues, key); foreach (var row in value[key]) { row.RawOptions = !string.IsNullOrWhiteSpace(rowOptionsDocTypeAlias) ? ConvertEditorToDb_DocType(rowOptionsDocTypeAlias, row.RawOptions) : null; foreach (var item in row.Items) { if (item != null && item.RawValue != null) { switch (item.Type.ToLowerInvariant()) { case "richtext": item.RawValue = ConvertEditorToDb_Fake(Constants.PropertyEditors.TinyMCEAlias, item.RawValue); break; case "embed": item.RawValue = ConvertEditorToDb_Fake(Constants.PropertyEditors.TextboxMultipleAlias, item.RawValue); break; case "doctype": if (item.AdditionalInfo.ContainsKey("docType") && item.AdditionalInfo["docType"] != null && !item.AdditionalInfo["docType"].IsNullOrWhiteSpace()) { // Lookup the doctype var docTypeAlias = item.AdditionalInfo["docType"]; // We make an assumption that the docTypeAlias is a Guid and attempt to parse it, // failing that we assume that the docTypeAlias is the actual alias. Guid docTypeGuid; if (Guid.TryParse(docTypeAlias, out docTypeGuid)) { docTypeAlias = ApplicationContext.Current.Services.ContentTypeService.GetAliasByGuid(docTypeGuid); // NOTE: [LK] As of v0.4.0 we want to persist the DocType's alias item.AdditionalInfo["docType"] = docTypeAlias; } // Serialize the dictionary back item.RawValue = ConvertEditorToDb_DocType(docTypeAlias, item.RawValue); } break; } } } } } return JsonConvert.SerializeObject(value); }
/// <summary> /// A method to deserialize the string value that has been saved in the content editor /// to an object to be stored in the database. /// </summary> /// <param name="editorValue"></param> /// <param name="currentValue"> /// The current value that has been persisted to the database for this editor. This value may be usesful for /// how the value then get's deserialized again to be re-persisted. In most cases it will probably not be used. /// </param> /// <returns></returns> /// <remarks> /// By default this will attempt to automatically convert the string value to the value type supplied by ValueType. /// /// If overridden then the object returned must match the type supplied in the ValueType, otherwise persisting the /// value to the DB will fail when it tries to validate the value type. /// </remarks> public virtual object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { var result = TryConvertValueToCrlType(editorValue.Value); if (result.Success == false) { LogHelper.Warn<PropertyValueEditor>("The value " + editorValue.Value + " cannot be converted to the type " + GetDatabaseType()); return null; } return result.Result; }
public static IPublishedContent ConvertValueToContent(string id, string docTypeAlias, string dataJson) { return (IPublishedContent)ApplicationContext.Current.ApplicationCache.RequestCache.GetCacheItem( "DocTypeGridEditorHelper.ConvertValueToContent_" + id + "_" + docTypeAlias, () => { using (var timer = DisposableTimer.DebugDuration<DocTypeGridEditorHelper>(string.Format("ConvertValueToContent ({0}, {1})", id, docTypeAlias))) { Guid docTypeGuid; if (Guid.TryParse(docTypeAlias, out docTypeGuid)) docTypeAlias = Services.ContentTypeService.GetAliasByGuid(docTypeGuid); var publishedContentType = PublishedContentType.Get(PublishedItemType.Content, docTypeAlias); var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(docTypeAlias); 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 = publishedContentType.GetPropertyType(jProp.Key); if (propType != null) { /* 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. */ var propEditor = PropertyEditorResolver.Current.GetByAlias(propType.PropertyEditorAlias); var propPreValues = Services.DataTypeService.GetPreValuesCollectionByDataTypeId( propType.DataTypeId); var contentPropData = new ContentPropertyData( jProp.Value == null ? null : jProp.Value.ToString(), propPreValues, new Dictionary<string, object>()); var newValue = propEditor.ValueEditor.ConvertEditorToDb(contentPropData, jProp.Value); /* Now that we have the DB stored value, we actually need to then convert it into it's * XML serialized state as expected by the published property by calling ConvertDbToString */ var propType2 = contentType.PropertyTypes.Single(x => x.Alias == propType.PropertyTypeAlias); var newValue2 = propEditor.ValueEditor.ConvertDbToString(new Property(propType2, newValue), propType2, ApplicationContext.Current.Services.DataTypeService); properties.Add(new DetachedPublishedProperty(propType, newValue2)); } } // Parse out the name manually object nameObj = null; if (propValues.TryGetValue("name", out nameObj)) { // Do nothing, we just want to parse out the name if we can } return new DetachedPublishedContent(nameObj == null ? null : nameObj.ToString(), publishedContentType, properties.ToArray()); } }); }
/// <summary> /// Overrides the deserialize value so that we can save the file accordingly /// </summary> /// <param name="editorValue"> /// This is value passed in from the editor. We normally don't care what the editorValue.Value is set to because /// we are more interested in the files collection associated with it, however we do care about the value if we /// are clearing files. By default the editorValue.Value will just be set to the name of the file (but again, we /// just ignore this and deal with the file collection in editorValue.AdditionalData.ContainsKey("files") ) /// </param> /// <param name="currentValue"> /// The current value persisted for this property. This will allow us to determine if we want to create a new /// file path or use the existing file path. /// </param> /// <returns></returns> public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { if (currentValue == null) { currentValue = string.Empty; } //if the value is the same then just return the current value so we don't re-process everything if (string.IsNullOrEmpty(currentValue.ToString()) == false && editorValue.Value == currentValue.ToString()) { return currentValue; } //check the editorValue value to see if we need to clear the files or not. var clear = false; var json = editorValue.Value as JObject; if (json != null && json["clearFiles"] != null && json["clearFiles"].Value<bool>()) { clear = json["clearFiles"].Value<bool>(); } var currentPersistedValues = new string[] {}; if (string.IsNullOrEmpty(currentValue.ToString()) == false) { currentPersistedValues = currentValue.ToString().Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries); } var newValue = new List<string>(); var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>(); if (clear) { //Remove any files that are saved for this item foreach (var toRemove in currentPersistedValues) { fs.DeleteFile(fs.GetRelativePath(toRemove), true); } return ""; } //check for any files if (editorValue.AdditionalData.ContainsKey("files")) { var files = editorValue.AdditionalData["files"] as IEnumerable<ContentItemFile>; if (files != null) { //now we just need to move the files to where they should be var filesAsArray = files.ToArray(); //a list of all of the newly saved files so we can compare with the current saved files and remove the old ones var savedFilePaths = new List<string>(); for (var i = 0; i < filesAsArray.Length; i++) { var file = filesAsArray[i]; //don't continue if this is not allowed! if (UploadFileTypeValidator.ValidateFileExtension(file.FileName) == false) { continue; } //TODO: ALl of this naming logic needs to be put into the ImageHelper and then we need to change ContentExtensions to do the same! var currentPersistedFile = currentPersistedValues.Length >= (i + 1) ? currentPersistedValues[i] : ""; var name = IOHelper.SafeFileName(file.FileName.Substring(file.FileName.LastIndexOf(IOHelper.DirSepChar) + 1, file.FileName.Length - file.FileName.LastIndexOf(IOHelper.DirSepChar) - 1).ToLower()); var subfolder = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? currentPersistedFile.Replace(fs.GetUrl("/"), "").Split('/')[0] : currentPersistedFile.Substring(currentPersistedFile.LastIndexOf("/", StringComparison.Ordinal) + 1).Split('-')[0]; int subfolderId; var numberedFolder = int.TryParse(subfolder, out subfolderId) ? subfolderId.ToString(CultureInfo.InvariantCulture) : MediaSubfolderCounter.Current.Increment().ToString(CultureInfo.InvariantCulture); var fileName = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories ? Path.Combine(numberedFolder, name) : numberedFolder + "-" + name; using (var fileStream = File.OpenRead(file.TempFilePath)) { var umbracoFile = UmbracoMediaFile.Save(fileStream, fileName); if (umbracoFile.SupportsResizing) { var additionalSizes = new List<int>(); //get the pre-vals value var thumbs = editorValue.PreValues.FormatAsDictionary(); if (thumbs.Any()) { var thumbnailSizes = thumbs.First().Value.Value; // additional thumbnails configured as prevalues on the DataType var sep = (thumbnailSizes.Contains("") == false && thumbnailSizes.Contains(",")) ? ',' : ';'; foreach (var thumb in thumbnailSizes.Split(sep)) { int thumbSize; if (thumb == "" || int.TryParse(thumb, out thumbSize) == false) continue; additionalSizes.Add(thumbSize); } } using (var image = Image.FromStream(fileStream)) { ImageHelper.GenerateMediaThumbnails(fs, fileName, umbracoFile.Extension, image, additionalSizes); } } newValue.Add(umbracoFile.Url); //add to the saved paths savedFilePaths.Add(umbracoFile.Url); } //now remove the temp file File.Delete(file.TempFilePath); } //Remove any files that are no longer saved for this item foreach (var toRemove in currentPersistedValues.Except(savedFilePaths)) { fs.DeleteFile(fs.GetRelativePath(toRemove), true); } return string.Join(",", newValue); } } //if we've made it here, we had no files to save and we were not clearing anything so just persist the same value we had before return currentValue; }
/// <summary> /// The value passed in from the editor will be an array of simple objects so we'll need to parse them to get the string /// </summary> /// <param name="editorValue"></param> /// <param name="currentValue"></param> /// <returns></returns> /// <remarks> /// We will also check the pre-values here, if there are more items than what is allowed we'll just trim the end /// </remarks> public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue) { var asArray = editorValue.Value as JArray; if (asArray == null) { return null; } var preVals = editorValue.PreValues.FormatAsDictionary(); var max = -1; if (preVals.Any()) { try { var json = JsonConvert.DeserializeObject<JObject>(preVals.First().Value.Value); max = int.Parse(json["Maximum"].ToString()); } catch (Exception) { //swallow max = -1; } } //The legacy property editor saved this data as new line delimited! strange but we have to maintain that. var array = asArray.OfType<JObject>() .Where(x => x["value"] != null) .Select(x => x["value"].Value<string>()); //only allow the max if over 0 if (max > 0) { return string.Join(Environment.NewLine, array.Take(max)); } return string.Join(Environment.NewLine, array); }
public TagPropertyEditorTagDefinition(ContentPropertyData propertySaving, SupportTagsAttribute tagsAttribute) : base(propertySaving, tagsAttribute) { }