diff --git a/src/Umbraco.StorageProviders.AzureBlob/CdnMediaUrlProvider.cs b/src/Umbraco.StorageProviders.AzureBlob/CdnMediaUrlProvider.cs index 5c7c55d..48d786e 100644 --- a/src/Umbraco.StorageProviders.AzureBlob/CdnMediaUrlProvider.cs +++ b/src/Umbraco.StorageProviders.AzureBlob/CdnMediaUrlProvider.cs @@ -1,8 +1,11 @@ using System; using Microsoft.Extensions.Options; +using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PropertyEditors; using Umbraco.Cms.Core.Routing; +using Umbraco.Extensions; namespace Umbraco.StorageProviders.AzureBlob { @@ -14,45 +17,89 @@ public class CdnMediaUrlProvider : DefaultMediaUrlProvider { private bool _removeMediaFromPath; private Uri _cdnUrl; + private string _mediaPath; /// - /// Creates a new instance of . + /// Initializes a new instance of the class. /// /// The options. + /// The global settings. + /// The hosting environment. /// The media path generators. /// The URI utility. - /// options - public CdnMediaUrlProvider(IOptionsMonitor options, - MediaUrlGeneratorCollection mediaPathGenerators, UriUtility uriUtility) + /// is null. + /// is null. + /// is null. + public CdnMediaUrlProvider(IOptionsMonitor options, IOptionsMonitor globalSettings, IHostingEnvironment hostingEnvironment, MediaUrlGeneratorCollection mediaPathGenerators, UriUtility uriUtility) + : this(options, mediaPathGenerators, uriUtility, string.Empty) + { + if (globalSettings == null) throw new ArgumentNullException(nameof(globalSettings)); + if (hostingEnvironment == null) throw new ArgumentNullException(nameof(hostingEnvironment)); + + _mediaPath = hostingEnvironment.ToAbsolute(globalSettings.CurrentValue.UmbracoMediaPath).EnsureEndsWith('/'); + + globalSettings.OnChange((options, name) => + { + if (name == Options.DefaultName) + { + _mediaPath = hostingEnvironment.ToAbsolute(options.UmbracoMediaPath).EnsureEndsWith('/'); + } + }); + } + + /// + /// Initializes a new instance of the class. + /// + /// The options. + /// The media path generators. + /// The URI utility. + /// is null. + [Obsolete("This constructor is obsolete and will be removed in a future version. Use another constructor instead.")] + public CdnMediaUrlProvider(IOptionsMonitor options, MediaUrlGeneratorCollection mediaPathGenerators, UriUtility uriUtility) + : this(options, mediaPathGenerators, uriUtility, "/media/") + { } + + private CdnMediaUrlProvider(IOptionsMonitor options, MediaUrlGeneratorCollection mediaPathGenerators, UriUtility uriUtility, string mediaPath) : base(mediaPathGenerators, uriUtility) { if (options == null) throw new ArgumentNullException(nameof(options)); _cdnUrl = options.CurrentValue.Url; _removeMediaFromPath = options.CurrentValue.RemoveMediaFromPath; + _mediaPath = mediaPath; - options.OnChange(OptionsOnChange); + options.OnChange((options, name) => + { + if (name == Options.DefaultName) + { + _removeMediaFromPath = options.RemoveMediaFromPath; + _cdnUrl = options.Url; + } + }); } /// public override UrlInfo? GetMediaUrl(IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current) { var mediaUrl = base.GetMediaUrl(content, propertyAlias, UrlMode.Relative, culture, current); - if (mediaUrl == null) return null; - - return mediaUrl.IsUrl switch + if (mediaUrl?.IsUrl == true) { - false => mediaUrl, - _ => UrlInfo.Url($"{_cdnUrl}/{mediaUrl.Text[(_removeMediaFromPath ? "/media/" : "/").Length..]}", culture) - }; - } + string url = mediaUrl.Text; - private void OptionsOnChange(CdnMediaUrlProviderOptions options, string name) - { - if (name != Options.DefaultName) return; + int startIndex = 0; + if (_removeMediaFromPath && url.StartsWith(_mediaPath, StringComparison.OrdinalIgnoreCase)) + { + startIndex = _mediaPath.Length; + } + else if (url.StartsWith('/')) + { + startIndex = 1; + } + + return UrlInfo.Url(_cdnUrl + url[startIndex..], culture); + } - _removeMediaFromPath = options.RemoveMediaFromPath; - _cdnUrl = options.Url; + return mediaUrl; } } }