Last active
March 10, 2016 04:49
-
-
Save JimBobSquarePants/9a41a19524ad9a0c210b to your computer and use it in GitHub Desktop.
ImageCropperPropertyConverter for Umbraco
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // -------------------------------------------------------------------------------------------------------------------- | |
| // <copyright file="ImageCropperPropertyConverter.cs" company="Deepend"> | |
| // Copyright (c) Deepend | |
| // </copyright> | |
| // <summary> | |
| // The image cropper property converter. This allows Ditto to map the image cropper using the built in Umbraco | |
| // methods. | |
| // </summary> | |
| // -------------------------------------------------------------------------------------------------------------------- | |
| namespace Deepend.Umbraco.ComponentModel | |
| { | |
| using System; | |
| using System.Globalization; | |
| using System.Linq; | |
| using Newtonsoft.Json; | |
| using global::Umbraco.Core; | |
| using global::Umbraco.Core.Logging; | |
| using global::Umbraco.Core.Models; | |
| using global::Umbraco.Core.Models.PublishedContent; | |
| using global::Umbraco.Core.PropertyEditors; | |
| using global::Umbraco.Core.Services; | |
| using global::Umbraco.Web.Models; | |
| using Newtonsoft.Json.Linq; | |
| /// <summary> | |
| /// The image cropper property converter. This allows Ditto to map the image cropper using the built in Umbraco | |
| /// methods. | |
| /// </summary> | |
| /// <remarks> | |
| /// This converter is based on the ImageCropperValueConverter added in Umbraco 7.4.0. | |
| /// When we update the base library to that version we will remove this one. | |
| /// </remarks> | |
| public class ImageCropperPropertyConverter : PropertyValueConverterBase, IPropertyValueConverterMeta | |
| { | |
| /// <summary> | |
| /// The data type service | |
| /// </summary> | |
| private readonly IDataTypeService dataTypeService; | |
| /// <summary> | |
| /// Initializes a new instance of the <see cref="ImageCropperPropertyConverter"/> class. | |
| /// </summary> | |
| public ImageCropperPropertyConverter() | |
| { | |
| this.dataTypeService = ApplicationContext.Current.Services.DataTypeService; | |
| } | |
| /// <summary> | |
| /// Initializes a new instance of the <see cref="ImageCropperPropertyConverter"/> class. | |
| /// </summary> | |
| /// <param name="dataTypeService"> | |
| /// Provides easy access to operations involving <see cref="T:Umbraco.Core.Models.IDataTypeDefinition"/> | |
| /// </param> | |
| public ImageCropperPropertyConverter(IDataTypeService dataTypeService) | |
| { | |
| if (dataTypeService == null) | |
| { | |
| throw new ArgumentNullException(nameof(dataTypeService)); | |
| } | |
| this.dataTypeService = dataTypeService; | |
| } | |
| /// <summary> | |
| /// Converts a property Data value to a Source value. | |
| /// </summary> | |
| /// <param name="propertyType">The property type.</param><param name="source">The data value.</param> | |
| /// <param name="preview">A value indicating whether conversion should take place in preview mode.</param> | |
| /// <returns> | |
| /// The result of the conversion. | |
| /// </returns> | |
| /// <remarks> | |
| /// <para> | |
| /// The converter should know how to convert a <c>null</c> raw value, meaning that no | |
| /// value has been assigned to the property. The source value can be <c>null</c>. | |
| /// </para> | |
| /// <para> | |
| /// With the XML cache, raw values come from the XML cache and therefore are strings. | |
| /// </para> | |
| /// <para> | |
| /// With objects caches, raw values would come from the database and therefore be either | |
| /// ints, DateTimes, or strings. | |
| /// </para> | |
| /// <para> | |
| /// The converter should be prepared to handle both situations. | |
| /// </para> | |
| /// <para> | |
| /// When raw values are strings, the converter must handle empty strings, whitespace | |
| /// strings, and xml-whitespace strings appropriately, ie it should know whether to preserve | |
| /// whitespaces. | |
| /// </para> | |
| /// </remarks> | |
| public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview) | |
| { | |
| if (source == null) | |
| { | |
| return null; | |
| } | |
| string sourceString = source.ToString(); | |
| try | |
| { | |
| JObject json = JsonConvert.DeserializeObject<JObject>( | |
| sourceString, | |
| new JsonSerializerSettings | |
| { | |
| Culture = CultureInfo.InvariantCulture, | |
| FloatParseHandling = FloatParseHandling.Decimal | |
| }); | |
| MergePreValues(json, this.dataTypeService, propertyType.DataTypeId); | |
| JsonSerializer serializer = new JsonSerializer | |
| { | |
| Culture = CultureInfo.InvariantCulture, | |
| FloatParseHandling = FloatParseHandling.Decimal | |
| }; | |
| // Return the strongly typed model | |
| return json.ToObject<ImageCropDataSet>(serializer); | |
| } | |
| catch (Exception ex) | |
| { | |
| LogHelper.Error<ImageCropperPropertyConverter>( | |
| $"Could not parse the string {sourceString} to a ImageCropDataSet object", | |
| ex); | |
| // It's not json, just return the string | |
| return sourceString; | |
| } | |
| } | |
| /// <summary> | |
| /// Gets a value indicating whether the converter supports a property type. | |
| /// </summary> | |
| /// <param name="propertyType">The property type.</param> | |
| /// <returns> | |
| /// A value indicating whether the converter supports a property type. | |
| /// </returns> | |
| public override bool IsConverter(PublishedPropertyType propertyType) | |
| { | |
| return Constants.PropertyEditors.ImageCropperAlias.InvariantEquals(propertyType.PropertyEditorAlias); | |
| } | |
| /// <summary> | |
| /// Gets the property cache level of a specified value. | |
| /// </summary> | |
| /// <param name="propertyType">The property type.</param><param name="cacheValue">The property value.</param> | |
| /// <returns> | |
| /// The property cache level of the specified value. | |
| /// </returns> | |
| public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue) | |
| { | |
| return PropertyCacheLevel.Content; | |
| } | |
| /// <summary> | |
| /// Gets the type of values returned by the converter. | |
| /// </summary> | |
| /// <param name="propertyType">The property type.</param> | |
| /// <returns> | |
| /// The CLR type of values returned by the converter. | |
| /// </returns> | |
| public Type GetPropertyValueType(PublishedPropertyType propertyType) | |
| { | |
| return typeof(ImageCropDataSet); | |
| } | |
| /// <summary> | |
| /// Merges pre values with the values for this data type. | |
| /// </summary> | |
| /// <param name="currentValue">The current value.</param> | |
| /// <param name="dataTypeService"> | |
| /// Provides easy access to operations involving <see cref="T:Umbraco.Core.Models.IDataTypeDefinition"/> | |
| /// </param> | |
| /// <param name="dataTypeId">The data type id.</param> | |
| internal static void MergePreValues(JObject currentValue, IDataTypeService dataTypeService, int dataTypeId) | |
| { | |
| // Need to lookup the pre-values for this data type | |
| // TODO: Change all singleton access to use ctor injection in v8!!! | |
| PreValueCollection prevalues = dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId); | |
| if (prevalues != null && prevalues.IsDictionaryBased && prevalues.PreValuesAsDictionary.ContainsKey("crops")) | |
| { | |
| string cropsString = prevalues.PreValuesAsDictionary["crops"].Value; | |
| JArray preValueCrops; | |
| try | |
| { | |
| preValueCrops = JsonConvert.DeserializeObject<JArray>(cropsString); | |
| } | |
| catch (Exception ex) | |
| { | |
| LogHelper.Error<ImageCropperPropertyConverter>($"Could not parse the string {cropsString} to a json object", ex); | |
| return; | |
| } | |
| // Now we need to merge the crop values - the alias + width + height comes from pre-configured pre-values, | |
| // however, each crop can store it's own coordinates | |
| JArray existingCropsArray; | |
| if (currentValue["crops"] != null) | |
| { | |
| existingCropsArray = (JArray)currentValue["crops"]; | |
| } | |
| else | |
| { | |
| currentValue["crops"] = existingCropsArray = new JArray(); | |
| } | |
| foreach (JToken preValueCrop in preValueCrops.Where(x => x.HasValues)) | |
| { | |
| JToken found = existingCropsArray.FirstOrDefault(x => | |
| { | |
| if (x.HasValues && x["alias"] != null) | |
| { | |
| return x["alias"].Value<string>() == preValueCrop["alias"].Value<string>(); | |
| } | |
| return false; | |
| }); | |
| if (found != null) | |
| { | |
| found["width"] = preValueCrop["width"]; | |
| found["height"] = preValueCrop["height"]; | |
| } | |
| else | |
| { | |
| existingCropsArray.Add(preValueCrop); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment