Skip to content

Commit

Permalink
Misc optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
abjerner committed Dec 19, 2024
1 parent 9a67a73 commit 7913c70
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 31 deletions.
15 changes: 15 additions & 0 deletions src/Limbo.Umbraco.Migrations/Constants/UmbracoMediaTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Limbo.Umbraco.Migrations.Constants;

public static class UmbracoMediaTypes {

public const string Article = global::Umbraco.Cms.Core.Constants.Conventions.MediaTypes.ArticleAlias;

public const string Video = global::Umbraco.Cms.Core.Constants.Conventions.MediaTypes.VideoAlias;

public const string VectorGraphics = global::Umbraco.Cms.Core.Constants.Conventions.MediaTypes.VectorGraphicsAlias;

public const string Pdf = Article;

public const string Svg = VectorGraphics;

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ public override bool IsConverter(ILegacyElement owner, ILegacyProperty property)
}

public override object? Convert(ILegacyElement owner, ILegacyProperty property) {

// TODO: Save the value as an object for Umbraco 13

string value = property.Value.ToString();
return string.IsNullOrWhiteSpace(value) ? null : MigrationsService.ConvertRte(property.Value.ToString());
return string.IsNullOrWhiteSpace(value) ? null : MigrationsService.ConvertRte(property.Value.ToString(), out _);
}

}
34 changes: 34 additions & 0 deletions src/Limbo.Umbraco.Migrations/Extensions/MigrationsExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Limbo.Umbraco.Migrations.Constants;
using Limbo.Umbraco.Migrations.Models.UrlPicker;
using Limbo.Umbraco.MigrationsClient.Models.Content;
using Limbo.Umbraco.MigrationsClient.Models.Umbraco;
using Skybrud.Essentials.Exceptions;
using Umbraco.Cms.Core.Models;
using Umbraco.Extensions;

using UmbracoGuidUdi = Umbraco.Cms.Core.GuidUdi;

namespace Limbo.Umbraco.Migrations.Extensions;

public static class MigrationsExtensions {

public static UmbracoGuidUdi? ToUmbracoUdi(this GuidUdi? udi) {
return udi is null ? null : new UmbracoGuidUdi(udi.EntityType, udi.Guid);
}

public static UrlPickerList AddContent(this UrlPickerList list, LegacyContent content, string? target = null, string? queryString = null) {
list.Add(UrlPickerItem.CreateContentItem(content.Name, new UmbracoGuidUdi(UmbracoEntityTypes.Content, content.Key), content.Url, target, queryString));
return list;
}

public static UrlPickerList AddMedia(this UrlPickerList list, IMedia media, string? target = null, string? queryString = null) {
string url = media.GetValue<string>("umbracoFile") ?? throw new BjernerSaysNoException();
list.Add(UrlPickerItem.CreateMediaItem(media.Name!, media.GetUdi(), url, target, queryString));
return list;
}

public static UrlPickerList? NullIfEmpty(this UrlPickerList? list) {
return list is null || list.Count == 0 ? null : list;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

<!-- Include NuGet dependencies -->
<ItemGroup>
<PackageReference Include="Limbo.Umbraco.MigrationsClient" Version="1.0.8" />
<PackageReference Include="Limbo.Umbraco.MigrationsClient" Version="1.0.9-build202412121617" />
<PackageReference Include="Skybrud.Essentials" Version="1.1.57" />
<PackageReference Include="Skybrud.Umbraco.GridData" Version="13.0.0" />
<PackageReference Include="Umbraco.Cms.Core" Version="[13.0.0,13.999)" />
Expand Down
20 changes: 20 additions & 0 deletions src/Limbo.Umbraco.Migrations/Models/Warning.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Limbo.Umbraco.Migrations.Models;

public class Warning {

public string Message { get; }

public Exception? Exception { get; }

public Warning(string message) {
Message = message;
}

public Warning(string message, Exception? exception) {
Message = message;
Exception = exception;
}

}
5 changes: 3 additions & 2 deletions src/Limbo.Umbraco.Migrations/Services/IMigrationsService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Limbo.Umbraco.Migrations.Models;
using Limbo.Umbraco.Migrations.Models.BlockList;
using Limbo.Umbraco.Migrations.Models.Rte;
using Limbo.Umbraco.Migrations.Models.UrlPickerItem;
using Limbo.Umbraco.Migrations.Models.UrlPicker;
using Limbo.Umbraco.MigrationsClient.Models.Skybrud.LinkPicker;
using Skybrud.Umbraco.GridData.Models;
using Umbraco.Cms.Core;
Expand Down Expand Up @@ -44,7 +45,7 @@ public interface IMigrationsService {

bool TryParseUdi(string? value, [NotNullWhen(true)] out GuidUdi? result);

RteModel? ConvertRte(string? input);
RteModel? ConvertRte(string? input, out IReadOnlyList<Warning> warnings);

UrlPickerList? ConvertLinkPickerList(LinkPickerList? list);

Expand Down
76 changes: 57 additions & 19 deletions src/Limbo.Umbraco.Migrations/Services/MigrationsServiceBase.Rte.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
using Umbraco.Cms.Core;
using Umbraco.Extensions;
using System.Collections.Generic;
using Limbo.Umbraco.Migrations.Models;
using Limbo.Umbraco.Migrations.Models.Rte;
using Limbo.Umbraco.MigrationsClient.Models.Media;

namespace Limbo.Umbraco.Migrations.Services;

Expand All @@ -18,8 +20,12 @@ public partial class MigrationsServiceBase {
/// Converts the specified RTE <paramref name="input"/> string.
/// </summary>
/// <param name="input">The RTE input string to be converted.</param>
/// <param name="warnings">When this method returns, holds a list of warnings.</param>
/// <returns>An instance of <see cref="string"/> representing the reuslt of the conversion.</returns>
public virtual RteModel? ConvertRte(string? input) {
public virtual RteModel? ConvertRte(string? input, out IReadOnlyList<Warning> warnings) {

List<Warning> warningsList = [];
warnings = warningsList;

// Return null right away if input is null or white space
if (string.IsNullOrWhiteSpace(input)) return null;
Expand All @@ -32,26 +38,26 @@ public partial class MigrationsServiceBase {
bool modified = false;

// Convert images and links
ConvertRteImages(document.DocumentNode, ref modified);
ConvertRteLinks(document.DocumentNode, ref modified);
ConvertRteImages(document.DocumentNode, warningsList, ref modified);
ConvertRteLinks(document.DocumentNode, warningsList, ref modified);

// If the HTML was modified, we convert it back to a string - otherwise we return "input" directly
return new RteModel(modified ? document.DocumentNode.OuterHtml : input);

}

protected virtual void ConvertRteLinks(HtmlNode root, ref bool modified) {
protected virtual void ConvertRteLinks(HtmlNode root, List<Warning> warnings, ref bool modified) {

IEnumerable<HtmlNode>? anchorLinks = root.Descendants("a");
if (anchorLinks is null) return;

foreach (HtmlNode link in anchorLinks) {
ConvertRteLink(link, ref modified);
ConvertRteLink(link, warnings, ref modified);
}

}

protected virtual void ConvertRteLink(HtmlNode link, ref bool modified) {
protected virtual void ConvertRteLink(HtmlNode link, List<Warning> warnings, ref bool modified) {

string href = link.GetAttributeValue("href", "");
string dataUdi = link.GetAttributeValue("data-udi", "");
Expand All @@ -61,8 +67,12 @@ protected virtual void ConvertRteLink(HtmlNode link, ref bool modified) {
// correct format. Also notice that the REGEX doesn't match until the end of the line. This is because
// "localLink" references may also include a fragment part (#)
if (RegexUtils.IsMatch(href, @"^\/{localLink:(umb:\/\/media\/([a-z0-9]{32}))", out string udiRaw)) {
if (UdiParser.TryParse(udiRaw, out GuidUdi? mediaUdi) && mediaUdi is not null) {
ImportMedia(mediaUdi.Guid);
if (UdiParser.TryParse(udiRaw, out GuidUdi? mediaUdi)) {
try {
ImportMedia(mediaUdi.Guid);
} catch (Exception ex) when (Is404(ex)) {
warnings.Add(new Warning($"Media with key '{mediaUdi.Guid}' not found.", ex));
}
return;
}
}
Expand Down Expand Up @@ -93,13 +103,19 @@ protected virtual void ConvertRteLink(HtmlNode link, ref bool modified) {
// Older Umbraco sites may specify the UDI via a data attribute, in which case we remove the "data-udi"
// attribute and set/update the "href" attribute instead. Also, if the UDI reference is for a media, we make
// sure to import said media
if (UdiParser.TryParse(dataUdi, out GuidUdi? udi) && udi is not null) {
if (UdiParser.TryParse(dataUdi, out GuidUdi? udi)) {

// Remove the legacy attribute
link.Attributes["data-udi"].Remove();

// If UDI reference a media, we import that media
if (udi.EntityType == UmbracoEntityTypes.Media) ImportMedia(udi.Guid);
if (udi.EntityType == UmbracoEntityTypes.Media) {
try {
ImportMedia(udi.Guid);
} catch (Exception ex) when (Is404(ex)) {
warnings.Add(new Warning($"Media with key '{udi.Guid}' not found.", ex));
}
}

// Update the "href" attribute
link.SetAttributeValue("href", $"/{{localLink:{udi}}}");
Expand All @@ -110,31 +126,38 @@ protected virtual void ConvertRteLink(HtmlNode link, ref bool modified) {

}

protected virtual void ConvertRteImages(HtmlNode root, ref bool modified) {
protected virtual void ConvertRteImages(HtmlNode root, List<Warning> warnings, ref bool modified) {

IEnumerable<HtmlNode>? images = root.Descendants("img");
if (images is null) return;

foreach (HtmlNode img in images) {
ConvertRteImage(img, ref modified);
ConvertRteImage(img, warnings, ref modified);
}

}

protected virtual void ConvertRteImage(HtmlNode img, ref bool modified) {
protected virtual void ConvertRteImage(HtmlNode img, List<Warning> warnings, ref bool modified) {

string src = img.GetAttributeValue("src", "");
string dataUdi = img.GetAttributeValue("data-udi", "");
string src = img.GetAttributeValue("src", "").Trim();
string dataUdi = img.GetAttributeValue("data-udi", "").Trim();

if (UdiParser.TryParse(dataUdi, out GuidUdi? udi) && udi is not null) {
if (UdiParser.TryParse(dataUdi, out GuidUdi? udi)) {

switch (udi.EntityType) {

case UmbracoEntityTypes.Media: {

// Import the referenced media
IMedia? media = ImportMedia(udi.Guid);
if (media is null) return;
IMedia? media;

try {
media = ImportMedia(udi.Guid);
if (media is null) return;
} catch (Exception ex) when(Is404(ex)) {
warnings.Add(new Warning($"Media with key '{udi.Guid}' not found.", ex));
return;
}

// Try to get the relative path to the media file (aka the URL)
if (!media.TryGetMediaPath("umbracoFile", Dependencies.MediaUrlGeneratorCollection, out string? mediaFilePath)) {
Expand All @@ -159,7 +182,22 @@ protected virtual void ConvertRteImage(HtmlNode img, ref bool modified) {

}

throw new Exception("Found unhandled <img /> element\r\n\r\n" + img.OuterHtml + "\r\n\r\n");
// Handle local media path references
if (src.StartsWith("/media/")) {
string path = src.Split('?')[0];
try {
LegacyMedia media = MigrationsClient.GetMediaByPath(path);
ImportMedia(media.Key);
} catch (Exception ex) when (Is404(ex)) {
warnings.Add(new Warning($"Media with path '{path}' not found.", ex));
}
return;
}

// Handle "external" media path references
if (src.Contains("/media/")) {
throw new MigrationsException($"Unexpected media URL '{src}' in RTE value.");
}

}

Expand Down
Loading

0 comments on commit 7913c70

Please sign in to comment.