Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Media Picker v2 to v3 progressively #10504

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/Umbraco.Core/Serialization/MediaWithCropsDtoConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.PropertyEditors.ValueConverters;

namespace Umbraco.Core.Serialization
{
public class MediaWithCropsDtoConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var mediaWithCropsDto = new List<MediaWithCropsDto>();

var mediaIds = value.ToString().Split(',');
if (mediaIds.Any())
{
foreach (var mediaId in mediaIds)
{
Guid mediaItemKey = default;
if (GuidUdi.TryParse(mediaId, out var guidUdi))
{
mediaItemKey = guidUdi.Guid;
}

if (mediaItemKey != default)
{
mediaWithCropsDto.Add(new MediaWithCropsDto()
{
Key = Guid.NewGuid(),
MediaKey = mediaItemKey,
Crops = new List<ImageCropperValue.ImageCropperCrop>(),
FocalPoint = new ImageCropperValue.ImageCropperFocalPoint {Left = 0.5m, Top = 0.5m}
});
}
}
}

JToken.FromObject(mediaWithCropsDto).WriteTo(writer);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
}

/// <summary>
/// Model/DTO that represents the JSON that the MediaPicker3 stores
/// </summary>
[DataContract]
internal class MediaWithCropsDto
{
[DataMember(Name = "key")]
public Guid Key { get; set; }

[DataMember(Name = "mediaKey")]
public Guid MediaKey { get; set; }

[DataMember(Name = "crops")]
public IEnumerable<ImageCropperValue.ImageCropperCrop> Crops { get; set; }

[DataMember(Name = "focalPoint")]
public ImageCropperValue.ImageCropperFocalPoint FocalPoint { get; set; }
}
}
1 change: 1 addition & 0 deletions src/Umbraco.Core/Umbraco.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
<Compile Include="Persistence\Repositories\Implement\InstallationRepository.cs" />
<Compile Include="PropertyEditors\EyeDropperColorPickerConfiguration.cs" />
<Compile Include="PropertyEditors\ComplexPropertyEditorContentEventHandler.cs" />
<Compile Include="Serialization\MediaWithCropsDtoConverter.cs" />
<Compile Include="Services\IIconService.cs" />
<Compile Include="Services\Implement\InstallationService.cs" />
<Compile Include="Migrations\Upgrade\V_8_6_0\AddMainDomLock.cs" />
Expand Down

This file was deleted.

46 changes: 38 additions & 8 deletions src/Umbraco.Web/PropertyEditors/MediaPicker3PropertyEditor.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.PropertyEditors;
using Umbraco.Web.PropertyEditors.ValueConverters;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;

namespace Umbraco.Web.PropertyEditors
{
Expand All @@ -21,27 +24,55 @@ namespace Umbraco.Web.PropertyEditors
Icon = Constants.Icons.MediaImage)]
public class MediaPicker3PropertyEditor : DataEditor
{
private readonly ILogger _logger;

/// <summary>
/// Initializes a new instance of the <see cref="MediaPicker3PropertyEditor"/> class.
/// </summary>
public MediaPicker3PropertyEditor(ILogger logger)
: base(logger)
{
_logger = logger;
}

/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() => new MediaPicker3ConfigurationEditor();

protected override IDataValueEditor CreateValueEditor() => new MediaPicker3PropertyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new MediaPicker3PropertyValueEditor(Attribute, _logger);

internal class MediaPicker3PropertyValueEditor : DataValueEditor, IDataValueReference
{
private readonly ILogger _logger;

///<remarks>
/// Note: no FromEditor() and ToEditor() methods
/// We do not want to transform the way the data is stored in the DB and would like to keep a raw JSON string
/// Note: no FromEditor() method
/// Only transform the way the data is stored if it's not already JSON
/// </remarks>
public MediaPicker3PropertyValueEditor(DataEditorAttribute attribute) : base(attribute)
public MediaPicker3PropertyValueEditor(DataEditorAttribute attribute, ILogger logger) : base(attribute)
{
_logger = logger;
}

public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null,
string segment = null)
{
var value = property.GetValue(culture, segment)?.ToString();
if (value != null && value.DetectIsJson() == false)
{
// If the value is not yet JSON we'll try to convert it
try
{
value = JsonConvert.SerializeObject(value, Formatting.Indented, new MediaWithCropsDtoConverter());
property.SetValue(value);
}
catch (Exception ex)
{
_logger.Error<MediaWithCropsDtoConverter>(ex, $"Could not convert data to Media Picker v3 format, the data stored is: {value}");
}
}

// If it is already JSON, just continue as normal
return base.ToEditor(property, dataTypeService, culture, segment);
}

public IEnumerable<UmbracoEntityReference> GetReferences(object value)
Expand All @@ -51,14 +82,13 @@ public IEnumerable<UmbracoEntityReference> GetReferences(object value)
if (rawJson.IsNullOrWhiteSpace())
yield break;

var mediaWithCropsDtos = JsonConvert.DeserializeObject<MediaPickerWithCropsValueConverter.MediaWithCropsDto[]>(rawJson);
var mediaWithCropsDtos = JsonConvert.DeserializeObject<MediaWithCropsDto[]>(rawJson);

foreach (var mediaWithCropsDto in mediaWithCropsDtos)
{
yield return new UmbracoEntityReference(GuidUdi.Create(Constants.UdiEntityType.Media, mediaWithCropsDto.MediaKey));
}
}

}
}
}
3 changes: 0 additions & 3 deletions src/Umbraco.Web/PropertyEditors/MediaPickerConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ namespace Umbraco.Web.PropertyEditors
/// </summary>
public class MediaPickerConfiguration : IIgnoreUserStartNodesConfig
{
[ConfigurationField("notice", "You can NOT change the property editor", "obsoletemediapickernotice")]
public bool Notice { get; set; }

[ConfigurationField("multiPicker", "Pick multiple items", "boolean")]
public bool Multiple { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Serialization;
using Umbraco.Web.PublishedCache;

namespace Umbraco.Web.PropertyEditors.ValueConverters
Expand All @@ -16,10 +18,13 @@ public class MediaPickerWithCropsValueConverter : PropertyValueConverterBase
{

private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly ILogger _logger;

public MediaPickerWithCropsValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor)

public MediaPickerWithCropsValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger)
{
_publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor));
_logger = logger;
}

public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot;
Expand Down Expand Up @@ -57,7 +62,21 @@ public override object ConvertIntermediateToObject(IPublishedElement owner, IPub
return isMultiple ? mediaItems: null;
}

var dtos = JsonConvert.DeserializeObject<IEnumerable<MediaWithCropsDto>>(inter.ToString());
var value = inter.ToString();
if (value.DetectIsJson() == false)
{
// If the value is not yet JSON we'll try to convert it
try
{
value = JsonConvert.SerializeObject(value, Formatting.Indented, new MediaWithCropsDtoConverter());
}
catch (Exception ex)
{
_logger.Error<MediaWithCropsDtoConverter>(ex, $"Could not convert data to Media Picker v3 format, the data stored is: {value}");
}
}

var dtos = JsonConvert.DeserializeObject<IEnumerable<MediaWithCropsDto>>(value);

foreach(var media in dtos)
{
Expand Down Expand Up @@ -95,25 +114,5 @@ private object FirstOrDefault(IList mediaItems)
{
return mediaItems.Count == 0 ? null : mediaItems[0];
}


/// <summary>
/// Model/DTO that represents the JSON that the MediaPicker3 stores
/// </summary>
[DataContract]
internal class MediaWithCropsDto
{
[DataMember(Name = "key")]
public Guid Key { get; set; }

[DataMember(Name = "mediaKey")]
public Guid MediaKey { get; set; }

[DataMember(Name = "crops")]
public IEnumerable<ImageCropperValue.ImageCropperCrop> Crops { get; set; }

[DataMember(Name = "focalPoint")]
public ImageCropperValue.ImageCropperFocalPoint FocalPoint { get; set; }
}
}
}