Merge branch 'netcore/feature/move-mappings-after-httpcontext' into netcore/feature/executable-backoffice

# Conflicts:
#	src/Umbraco.Abstractions/CompositionExtensions.cs
This commit is contained in:
Bjarke Berg
2020-02-19 14:44:22 +01:00
374 changed files with 2356 additions and 1740 deletions
+9 -3
View File
@@ -25,16 +25,22 @@ dotnet_naming_rule.private_members_with_underscore.severity = suggestion
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
# dotnet_naming_symbols.private_fields.required_modifiers = abstract,async,readonly,static # all except const
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _
# https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/ide/editorconfig-code-style-settings-reference.md
[*.cs]
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
csharp_prefer_braces = false : none
csharp_prefer_braces = false : none
[*.{js,less}]
trim_trailing_whitespace = false
[*.{js,less}]
trim_trailing_whitespace = false
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text.RegularExpressions;
@@ -101,5 +102,9 @@ namespace Umbraco.Core.Cache
var compiled = new Regex(regex, RegexOptions.Compiled);
_items.RemoveAll(kvp => compiled.IsMatch(kvp.Key));
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
@@ -171,5 +171,20 @@ namespace Umbraco.Core.Cache
}
#endregion
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
if (!TryGetContextItems(out var items))
{
yield break;
}
foreach (DictionaryEntry item in items)
{
yield return new KeyValuePair<string, object>(item.Key.ToString(), item.Value);
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
@@ -1,6 +1,8 @@
using System.Collections.Generic;
namespace Umbraco.Core.Cache
{
public interface IRequestCache : IAppCache
public interface IRequestCache : IAppCache, IEnumerable<KeyValuePair<string, object>>
{
bool Set(string key, object value);
bool Remove(string key);
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -84,5 +85,9 @@ namespace Umbraco.Core.Cache
/// <inheritdoc />
public virtual void ClearByRegex(string regex)
{ }
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => new Dictionary<string, object>().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
@@ -1,4 +1,5 @@
using Umbraco.Core.Composing;
using Umbraco.Core.PropertyEditors;
using Umbraco.Web.Dashboards;
namespace Umbraco.Core
@@ -14,6 +15,7 @@ namespace Umbraco.Core
public static ComponentCollectionBuilder Components(this Composition composition)
=> composition.WithCollectionBuilder<ComponentCollectionBuilder>();
/// <summary>
/// Gets the backoffice dashboards collection builder.
/// </summary>
@@ -21,6 +23,15 @@ namespace Umbraco.Core
public static DashboardCollectionBuilder Dashboards(this Composition composition)
=> composition.WithCollectionBuilder<DashboardCollectionBuilder>();
/// <summary>
/// Gets the content finders collection builder.
/// </summary>
/// <param name="composition">The composition.</param>
/// <returns></returns>
public static MediaUrlGeneratorCollectionBuilder MediaUrlGenerators(this Composition composition)
=> composition.WithCollectionBuilder<MediaUrlGeneratorCollectionBuilder>();
#endregion
}
}
@@ -6,5 +6,7 @@ namespace Umbraco.Core.Configuration
{
get;
}
void RemoveConnectionString(string umbracoConnectionName);
}
}
+15
View File
@@ -19,6 +19,21 @@
public const string PreviewCookieName = "UMB_PREVIEW";
public const string InstallerCookieName = "umb_installId";
/// <summary>
/// The cookie name that is used to store the validation value
/// </summary>
public const string CsrfValidationCookieName = "UMB-XSRF-V";
/// <summary>
/// The cookie name that is set for angular to use to pass in to the header value for "X-UMB-XSRF-TOKEN"
/// </summary>
public const string AngularCookieName = "UMB-XSRF-TOKEN";
/// <summary>
/// The header name that angular uses to pass in the token to validate the cookie
/// </summary>
public const string AngularHeadername = "X-UMB-XSRF-TOKEN";
}
}
}
@@ -4,7 +4,6 @@ using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.ContentEditing;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Models.Membership;
namespace Umbraco.Web.ContentApps
@@ -12,18 +11,18 @@ namespace Umbraco.Web.ContentApps
public class ContentAppFactoryCollection : BuilderCollectionBase<IContentAppFactory>
{
private readonly ILogger _logger;
private readonly ICurrentUserAccessor _currentUserAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public ContentAppFactoryCollection(IEnumerable<IContentAppFactory> items, ILogger logger, ICurrentUserAccessor currentUserAccessor)
public ContentAppFactoryCollection(IEnumerable<IContentAppFactory> items, ILogger logger, IUmbracoContextAccessor umbracoContextAccessor)
: base(items)
{
_logger = logger;
_currentUserAccessor = currentUserAccessor;
_umbracoContextAccessor = umbracoContextAccessor;
}
private IEnumerable<IReadOnlyUserGroup> GetCurrentUserGroups()
{
var currentUser = _currentUserAccessor.TryGetCurrentUser();
var currentUser = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser;
return currentUser == null
? Enumerable.Empty<IReadOnlyUserGroup>()
: currentUser.Groups;
@@ -19,8 +19,8 @@ namespace Umbraco.Web.ContentApps
{
// get the logger just-in-time - see note below for manifest parser
var logger = factory.GetInstance<ILogger>();
var currentUserAccessor = factory.GetInstance<ICurrentUserAccessor>();
return new ContentAppFactoryCollection(CreateItems(factory), logger, currentUserAccessor);
var umbracoContextAccessor = factory.GetInstance<IUmbracoContextAccessor>();
return new ContentAppFactoryCollection(CreateItems(factory), logger, umbracoContextAccessor);
}
protected override IEnumerable<IContentAppFactory> CreateItems(IFactory factory)
@@ -0,0 +1,10 @@
namespace Umbraco.Core.Cookie
{
public interface ICookieManager
{
void ExpireCookie(string cookieName);
string GetCookieValue(string cookieName);
void SetCookieValue(string cookieName, string value);
bool HasCookie(string cookieName);
}
}
@@ -1,5 +1,4 @@
using Umbraco.Core.Collections;
using Umbraco.Web.WebApi;
namespace Umbraco.Web.Features
{
@@ -13,19 +12,19 @@ namespace Umbraco.Web.Features
/// </summary>
public DisabledFeatures()
{
Controllers = new TypeList<UmbracoApiControllerBase>();
Controllers = new TypeList<IUmbracoFeature>();
}
/// <summary>
/// Gets the disabled controllers.
/// </summary>
public TypeList<UmbracoApiControllerBase> Controllers { get; }
public TypeList<IUmbracoFeature> Controllers { get; }
/// <summary>
/// Disables the device preview feature of previewing.
/// </summary>
public bool DisableDevicePreview { get; set; }
/// <summary>
/// If true, all references to templates will be removed in the back office and routing
/// </summary>
@@ -0,0 +1,7 @@
namespace Umbraco.Web.Features
{
public interface IUmbracoFeature
{
}
}
@@ -1,5 +1,4 @@
using System;
using Umbraco.Web.WebApi;
namespace Umbraco.Web.Features
{
@@ -16,7 +15,7 @@ namespace Umbraco.Web.Features
Disabled = new DisabledFeatures();
Enabled = new EnabledFeatures();
}
/// <summary>
/// Gets the disabled features.
/// </summary>
@@ -32,7 +31,7 @@ namespace Umbraco.Web.Features
/// </summary>
internal bool IsControllerEnabled(Type feature)
{
if (typeof(UmbracoApiControllerBase).IsAssignableFrom(feature))
if (typeof(IUmbracoFeature).IsAssignableFrom(feature))
return Disabled.Controllers.Contains(feature) == false;
throw new NotSupportedException("Not a supported feature type.");
@@ -1,6 +1,7 @@
using System;
using System.Runtime.Remoting.Messaging;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Scoping;
namespace Umbraco.Web
{
@@ -16,13 +17,13 @@ namespace Umbraco.Web
public abstract class HybridAccessorBase<T>
where T : class
{
private readonly IRequestCache _requestCache;
// ReSharper disable StaticMemberInGenericType
private static readonly object Locker = new object();
private static bool _registered;
// ReSharper restore StaticMemberInGenericType
private readonly IHttpContextAccessor _httpContextAccessor;
protected abstract string ItemKey { get; }
// read
@@ -42,17 +43,16 @@ namespace Umbraco.Web
// yes! flows with async!
private T NonContextValue
{
get => (T) CallContext.LogicalGetData(ItemKey);
get => CallContext<T>.GetData(ItemKey);
set
{
if (value == null) CallContext.FreeNamedDataSlot(ItemKey);
else CallContext.LogicalSetData(ItemKey, value);
CallContext<T>.SetData(ItemKey, value);
}
}
protected HybridAccessorBase(IHttpContextAccessor httpContextAccessor)
protected HybridAccessorBase(IRequestCache requestCache)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
_requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache));
lock (Locker)
{
@@ -65,15 +65,14 @@ namespace Umbraco.Web
var itemKey = ItemKey; // virtual
SafeCallContext.Register(() =>
{
var value = CallContext.LogicalGetData(itemKey);
CallContext.FreeNamedDataSlot(itemKey);
var value = CallContext<T>.GetData(itemKey);
return value;
}, o =>
{
if (o == null) return;
var value = o as T;
if (value == null) throw new ArgumentException($"Expected type {typeof(T).FullName}, got {o.GetType().FullName}", nameof(o));
CallContext.LogicalSetData(itemKey, value);
CallContext<T>.SetData(itemKey, value);
});
}
@@ -81,20 +80,23 @@ namespace Umbraco.Web
{
get
{
var httpContext = _httpContextAccessor.HttpContext;
if (httpContext == null) return NonContextValue;
return (T) httpContext.Items[ItemKey];
if (!_requestCache.IsAvailable)
{
return NonContextValue;
}
return (T) _requestCache.Get(ItemKey);
}
set
{
var httpContext = _httpContextAccessor.HttpContext;
if (httpContext == null)
if (!_requestCache.IsAvailable)
{
NonContextValue = value;
}
else if (value == null)
httpContext.Items.Remove(ItemKey);
_requestCache.Remove(ItemKey);
else
httpContext.Items[ItemKey] = value;
_requestCache.Set(ItemKey, value);
}
}
}
@@ -1,4 +1,5 @@
using Umbraco.Core.Events;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
namespace Umbraco.Web
{
@@ -6,8 +7,8 @@ namespace Umbraco.Web
{
protected override string ItemKey => "Umbraco.Core.Events.HybridEventMessagesAccessor";
public HybridEventMessagesAccessor(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
public HybridEventMessagesAccessor(IRequestCache requestCache)
: base(requestCache)
{ }
public EventMessages EventMessages
@@ -1,5 +1,4 @@
using System;
using System.Web;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
@@ -16,11 +15,6 @@ namespace Umbraco.Web
/// </summary>
DateTime ObjectCreated { get; }
/// <summary>
/// This is used internally for debugging and also used to define anything required to distinguish this request from another.
/// </summary>
Guid UmbracoRequestId { get; }
/// <summary>
/// Gets the WebSecurity class
/// </summary>
@@ -62,11 +56,6 @@ namespace Umbraco.Web
/// </summary>
bool IsFrontEndUmbracoRequest { get; }
/// <summary>
/// Gets the url provider.
/// </summary>
IPublishedUrlProvider UrlProvider { get; }
/// <summary>
/// Gets/sets the PublishedRequest object
/// </summary>
@@ -88,40 +77,6 @@ namespace Umbraco.Web
/// </summary>
bool InPreviewMode { get; }
/// <summary>
/// Gets the url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
string Url(int contentId, string culture = null);
/// <summary>
/// Gets the url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
string Url(Guid contentId, string culture = null);
/// <summary>
/// Gets the url of a content identified by its identifier, in a specified mode.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="mode">The mode.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
string Url(int contentId, UrlMode mode, string culture = null);
/// <summary>
/// Gets the url of a content identified by its identifier, in a specified mode.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="mode">The mode.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
string Url(Guid contentId, UrlMode mode, string culture = null);
IDisposable ForcedPreview(bool preview);
void Dispose();
}
@@ -26,7 +26,6 @@ namespace Umbraco.Web
/// // use umbracoContext...
/// }
/// </example>
/// <param name="httpContext">An optional http context.</param>
UmbracoContextReference EnsureUmbracoContext(HttpContextBase httpContext = null);
UmbracoContextReference EnsureUmbracoContext();
}
}
}
@@ -7,10 +7,5 @@ namespace Umbraco.Core.Install
bool RunFilePermissionTestSuite(out Dictionary<string, IEnumerable<string>> report);
bool EnsureDirectories(string[] dirs, out IEnumerable<string> errors, bool writeCausesRestart = false);
bool EnsureFiles(string[] files, out IEnumerable<string> errors);
bool EnsureCanCreateSubDirectory(string dir, out IEnumerable<string> errors);
bool EnsureCanCreateSubDirectories(IEnumerable<string> dirs, out IEnumerable<string> errors);
bool TestPublishedSnapshotService(out IEnumerable<string> errors);
bool TryCreateDirectory(string dir);
bool TryAccessDirectory(string dir, bool canWrite);
}
}
@@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Collections;
using Umbraco.Web.Composing;
using Umbraco.Core.IO;
using Umbraco.Core.Serialization;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install
@@ -13,29 +13,37 @@ namespace Umbraco.Web.Install
/// <summary>
/// An internal in-memory status tracker for the current installation
/// </summary>
internal static class InstallStatusTracker
public class InstallStatusTracker
{
private readonly IIOHelper _ioHelper;
private readonly IJsonSerializer _jsonSerializer;
public InstallStatusTracker(IIOHelper ioHelper, IJsonSerializer jsonSerializer)
{
_ioHelper = ioHelper;
_jsonSerializer = jsonSerializer;
}
private static ConcurrentHashSet<InstallTrackingItem> _steps = new ConcurrentHashSet<InstallTrackingItem>();
private static string GetFile(Guid installId)
private string GetFile(Guid installId)
{
var file = Current.IOHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/"
+ "install_"
+ installId.ToString("N")
+ ".txt");
var file = _ioHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/"
+ "install_"
+ installId.ToString("N")
+ ".txt");
return file;
}
public static void Reset()
public void Reset()
{
_steps = new ConcurrentHashSet<InstallTrackingItem>();
ClearFiles();
}
public static void ClearFiles()
public void ClearFiles()
{
var dir = Current.IOHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/");
var dir = _ioHelper.MapPath(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "Install/");
if (Directory.Exists(dir))
{
var files = Directory.GetFiles(dir);
@@ -50,13 +58,13 @@ namespace Umbraco.Web.Install
}
}
public static IEnumerable<InstallTrackingItem> InitializeFromFile(Guid installId)
public IEnumerable<InstallTrackingItem> InitializeFromFile(Guid installId)
{
//check if we have our persisted file and read it
var file = GetFile(installId);
if (File.Exists(file))
{
var deserialized = JsonConvert.DeserializeObject<IEnumerable<InstallTrackingItem>>(
var deserialized = _jsonSerializer.Deserialize<IEnumerable<InstallTrackingItem>>(
File.ReadAllText(file));
foreach (var item in deserialized)
{
@@ -70,7 +78,7 @@ namespace Umbraco.Web.Install
return new List<InstallTrackingItem>(_steps);
}
public static IEnumerable<InstallTrackingItem> Initialize(Guid installId, IEnumerable<InstallSetupStep> steps)
public IEnumerable<InstallTrackingItem> Initialize(Guid installId, IEnumerable<InstallSetupStep> steps)
{
//if there are no steps in memory
if (_steps.Count == 0)
@@ -79,7 +87,7 @@ namespace Umbraco.Web.Install
var file = GetFile(installId);
if (File.Exists(file))
{
var deserialized = JsonConvert.DeserializeObject<IEnumerable<InstallTrackingItem>>(
var deserialized = _jsonSerializer.Deserialize<IEnumerable<InstallTrackingItem>>(
File.ReadAllText(file));
foreach (var item in deserialized)
{
@@ -96,7 +104,7 @@ namespace Umbraco.Web.Install
_steps.Add(new InstallTrackingItem(step.Name, step.ServerOrder));
}
//save the file
var serialized = JsonConvert.SerializeObject(new List<InstallTrackingItem>(_steps));
var serialized = _jsonSerializer.Serialize(new List<InstallTrackingItem>(_steps));
Directory.CreateDirectory(Path.GetDirectoryName(file));
File.WriteAllText(file, serialized);
}
@@ -110,7 +118,7 @@ namespace Umbraco.Web.Install
ClearFiles();
//save the correct file
var serialized = JsonConvert.SerializeObject(new List<InstallTrackingItem>(_steps));
var serialized = _jsonSerializer.Serialize(new List<InstallTrackingItem>(_steps));
Directory.CreateDirectory(Path.GetDirectoryName(file));
File.WriteAllText(file, serialized);
}
@@ -119,7 +127,7 @@ namespace Umbraco.Web.Install
return new List<InstallTrackingItem>(_steps);
}
public static void SetComplete(Guid installId, string name, IDictionary<string, object> additionalData = null)
public void SetComplete(Guid installId, string name, IDictionary<string, object> additionalData = null)
{
var trackingItem = _steps.Single(x => x.Name == name);
if (additionalData != null)
@@ -130,7 +138,7 @@ namespace Umbraco.Web.Install
//save the file
var file = GetFile(installId);
var serialized = JsonConvert.SerializeObject(new List<InstallTrackingItem>(_steps));
var serialized = _jsonSerializer.Serialize(new List<InstallTrackingItem>(_steps));
File.WriteAllText(file, serialized);
}
@@ -4,7 +4,6 @@ using System.IO;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Install;
using Umbraco.Core.IO;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using Umbraco.Web.Composing;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Web.Install.Models;
@@ -14,10 +14,12 @@ namespace Umbraco.Web.Install.InstallSteps
{
public override bool RequiresExecution(object model) => true;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IRuntimeState _runtimeState;
public UpgradeStep(IUmbracoVersion umbracoVersion)
public UpgradeStep(IUmbracoVersion umbracoVersion, IRuntimeState runtimeState)
{
_umbracoVersion = umbracoVersion;
_runtimeState = runtimeState;
}
public override Task<InstallSetupResult> ExecuteAsync(object model) => Task.FromResult<InstallSetupResult>(null);
@@ -43,9 +45,9 @@ namespace Umbraco.Web.Install.InstallSteps
return value;
}
var state = Current.RuntimeState; // TODO: inject
var currentState = FormatGuidState(state.CurrentMigrationState);
var newState = FormatGuidState(state.FinalMigrationState);
var currentState = FormatGuidState(_runtimeState.CurrentMigrationState);
var newState = FormatGuidState(_runtimeState.FinalMigrationState);
var reportUrl = $"https://our.umbraco.com/contribute/releases/compare?from={currentVersion}&to={newVersion}&notes=1";
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
namespace Umbraco.Web.Install.Models
{
@@ -9,7 +8,7 @@ namespace Umbraco.Web.Install.Models
public class InstallInstructions
{
[DataMember(Name = "instructions")]
public IDictionary<string, JToken> Instructions { get; set; }
public IDictionary<string, object> Instructions { get; set; }
[DataMember(Name = "installId")]
public Guid InstallId { get; set; }
@@ -3,7 +3,7 @@ using System.Runtime.Serialization;
namespace Umbraco.Web.Install.Models
{
internal class InstallTrackingItem
public class InstallTrackingItem
{
public InstallTrackingItem(string name, int serverOrder)
{
@@ -1,8 +1,8 @@
namespace Umbraco.Core.Models
{
internal static class MediaTypeExtensions
public static class MediaTypeExtensions
{
internal static bool IsSystemMediaType(this IMediaType mediaType) =>
public static bool IsSystemMediaType(this IMediaType mediaType) =>
mediaType.Alias == Constants.Conventions.MediaTypes.File
|| mediaType.Alias == Constants.Conventions.MediaTypes.Folder
|| mediaType.Alias == Constants.Conventions.MediaTypes.Image;
@@ -4,7 +4,7 @@ using Umbraco.Core;
namespace Umbraco.Web.Models.ContentEditing
{
[DataContract(Name = "link", Namespace = "")]
internal class LinkDisplay
public class LinkDisplay
{
[DataMember(Name = "icon")]
public string Icon { get; set; }
@@ -22,7 +22,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// We'll use this to map the categories but it wont' be returned in the json
/// </summary>
[IgnoreDataMember]
internal string Category { get; set; }
public string Category { get; set; }
/// <summary>
/// The letter from the IAction
@@ -75,7 +75,7 @@ namespace Umbraco.Core.Models
/// </summary>
/// <param name="dataType">The data type definition.</param>
/// <returns></returns>
internal static bool IsBuildInDataType(this IDataType dataType)
public static bool IsBuildInDataType(this IDataType dataType)
{
return IsBuildInDataType(dataType.Key);
}
@@ -83,7 +83,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Returns true if this date type is build-in/default.
/// </summary>
internal static bool IsBuildInDataType(Guid key)
public static bool IsBuildInDataType(Guid key)
{
return IdsOfBuildInDataTypes.Contains(key);
}
@@ -1,19 +0,0 @@
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Must be implemented by property editors that store media and return media paths
/// </summary>
/// <remarks>
/// Currently there are only 2x core editors that do this: upload and image cropper.
/// It would be possible for developers to know implement their own media property editors whereas previously this was not possible.
/// </remarks>
public interface IDataEditorWithMediaPath
{
/// <summary>
/// Returns the media path for the value stored for a property
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
string GetMediaPath(object value);
}
}
@@ -0,0 +1,18 @@
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Used to generate paths to media items for a specified property editor alias
/// </summary>
public interface IMediaUrlGenerator
{
/// <summary>
/// Tries to get a media path for a given property editor alias
/// </summary>
/// <param name="alias">The property editor alias</param>
/// <param name="value">The value of the property</param>
/// <returns>
/// True if a media path was returned
/// </returns>
bool TryGetMediaPath(string alias, object value, out string mediaPath);
}
}
@@ -1,13 +0,0 @@
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Models.Identity
{
public interface ICurrentUserAccessor
{
/// <summary>
/// Returns the current user or null if no user is currently authenticated.
/// </summary>
/// <returns>The current user or null</returns>
IUser TryGetCurrentUser();
}
}
@@ -1,4 +1,5 @@
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Cache;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Web.Models.PublishedContent
{
@@ -7,22 +8,22 @@ namespace Umbraco.Web.Models.PublishedContent
/// </summary>
public class HttpContextVariationContextAccessor : IVariationContextAccessor
{
public const string ContextKey = "Umbraco.Web.Models.PublishedContent.DefaultVariationContextAccessor";
public readonly IHttpContextAccessor HttpContextAccessor;
private readonly IRequestCache _requestCache;
private const string ContextKey = "Umbraco.Web.Models.PublishedContent.DefaultVariationContextAccessor";
/// <summary>
/// Initializes a new instance of the <see cref="HttpContextVariationContextAccessor"/> class.
/// </summary>
public HttpContextVariationContextAccessor(IHttpContextAccessor httpContextAccessor)
public HttpContextVariationContextAccessor(IRequestCache requestCache)
{
HttpContextAccessor = httpContextAccessor;
_requestCache = requestCache;
}
/// <inheritdoc />
public VariationContext VariationContext
{
get => (VariationContext) HttpContextAccessor.HttpContext?.Items[ContextKey];
set => HttpContextAccessor.HttpContext.Items[ContextKey] = value;
get => (VariationContext) _requestCache.Get(ContextKey);
set => _requestCache.Set(ContextKey, value);
}
}
}
@@ -1,14 +1,15 @@
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Cache;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Web.Models.PublishedContent
{
/// <summary>
/// Implements a hybrid <see cref="IVariationContextAccessor"/>.
/// </summary>
internal class HybridVariationContextAccessor : HybridAccessorBase<VariationContext>, IVariationContextAccessor
public class HybridVariationContextAccessor : HybridAccessorBase<VariationContext>, IVariationContextAccessor
{
public HybridVariationContextAccessor(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
public HybridVariationContextAccessor(IRequestCache requestCache)
: base(requestCache)
{ }
/// <inheritdoc />
@@ -23,4 +24,4 @@ namespace Umbraco.Web.Models.PublishedContent
set => Value = value;
}
}
}
}
@@ -182,7 +182,7 @@ namespace Umbraco.Web.Models.PublishedContent
// if we found a content with the property having a value, return that property value
if (property != null && property.HasValue(culture, segment))
{
value = property.Value<T>(culture, segment);
value = property.Value<T>(this, culture, segment);
return true;
}
@@ -216,7 +216,7 @@ namespace Umbraco.Web.Models.PublishedContent
if (property.HasValue(culture2, segment))
{
value = property.Value<T>(culture2, segment);
value = property.Value<T>(this, culture2, segment);
return true;
}
@@ -250,7 +250,7 @@ namespace Umbraco.Web.Models.PublishedContent
if (content.HasValue(alias, culture2, segment))
{
value = content.Value<T>(alias, culture2, segment);
value = content.Value<T>(this, alias, culture2, segment);
return true;
}
@@ -287,7 +287,7 @@ namespace Umbraco.Web.Models.PublishedContent
if (content.HasValue(alias, culture2, segment))
{
value = content.Value<T>(alias, culture2, segment);
value = content.Value<T>(this, alias, culture2, segment);
return true;
}
@@ -1,6 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Umbraco.Core;
using Umbraco.Core;
using Umbraco.Core.Services;
namespace Umbraco.Web.Models.Trees
@@ -5,7 +5,7 @@ using Umbraco.Core.Services;
namespace Umbraco.Web
{
internal static class PasswordConfigurationExtensions
public static class PasswordConfigurationExtensions
{
/// <summary>
/// Returns the configuration of the membership provider used to configure change password editors
@@ -8,7 +8,6 @@ using System.Runtime.InteropServices;
// Umbraco Cms
[assembly: InternalsVisibleTo("Umbraco.Web")]
[assembly: InternalsVisibleTo("Umbraco.Web.UI")]
[assembly: InternalsVisibleTo("Umbraco.Examine")]
[assembly: InternalsVisibleTo("Umbraco.ModelsBuilder.Embedded")]
[assembly: InternalsVisibleTo("Umbraco.Tests")]
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
public class MediaUrlGeneratorCollection : BuilderCollectionBase<IMediaUrlGenerator>
{
public MediaUrlGeneratorCollection(IEnumerable<IMediaUrlGenerator> items) : base(items)
{
}
public bool TryGetMediaPath(string alias, object value, out string mediaPath)
{
foreach(var generator in this)
{
if (generator.TryGetMediaPath(alias, value, out var mp))
{
mediaPath = mp;
return true;
}
}
mediaPath = null;
return false;
}
}
}
@@ -0,0 +1,9 @@
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
public class MediaUrlGeneratorCollectionBuilder : LazyCollectionBuilderBase<MediaUrlGeneratorCollectionBuilder, MediaUrlGeneratorCollection, IMediaUrlGenerator>
{
protected override MediaUrlGeneratorCollectionBuilder This => this;
}
}
@@ -167,7 +167,7 @@ namespace Umbraco.Web.PublishedCache
string StatusUrl { get; }
#endregion
#endregion
void Collect();
}
@@ -1,5 +1,4 @@
using System;
namespace Umbraco.Web.PublishedCache
{
public class UmbracoContextPublishedSnapshotAccessor : IPublishedSnapshotAccessor
@@ -5,6 +5,7 @@ using Umbraco.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
@@ -1087,6 +1088,8 @@ namespace Umbraco.Core
#endregion
#region Url
/// <summary>
/// Gets the url of the content item.
/// </summary>
@@ -1117,5 +1120,6 @@ namespace Umbraco.Core
}
}
#endregion
}
}
@@ -16,16 +16,18 @@ namespace Umbraco.Web.Routing
private readonly IGlobalSettings _globalSettings;
private readonly IRequestHandlerSection _requestConfig;
private readonly ISiteDomainHelper _siteDomainHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly UriUtility _uriUtility;
private readonly IPublishedValueFallback _publishedValueFallback;
public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSection requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback)
public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSection requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor)
{
_globalSettings = globalSettings;
_requestConfig = requestConfig;
_siteDomainHelper = siteDomainHelper;
_uriUtility = uriUtility;
_publishedValueFallback = publishedValueFallback;
_umbracoContextAccessor = umbracoContextAccessor;
}
// note - at the moment we seem to accept pretty much anything as an alias
@@ -35,7 +37,7 @@ namespace Umbraco.Web.Routing
#region GetUrl
/// <inheritdoc />
public UrlInfo GetUrl(IUmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current)
public UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string culture, Uri current)
{
return null; // we have nothing to say
}
@@ -55,8 +57,9 @@ namespace Umbraco.Web.Routing
/// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
/// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
/// </remarks>
public IEnumerable<UrlInfo> GetOtherUrls(IUmbracoContext umbracoContext, int id, Uri current)
public IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current)
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
var node = umbracoContext.Content.GetById(id);
if (node == null)
yield break;
@@ -17,13 +17,13 @@ namespace Umbraco.Web.Routing
{
private readonly IRedirectUrlService _redirectUrlService;
private readonly ILogger _logger;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IPublishedUrlProvider _publishedUrlProvider;
public ContentFinderByRedirectUrl(IRedirectUrlService redirectUrlService, ILogger logger, IUmbracoContextAccessor umbracoContextAccessor)
public ContentFinderByRedirectUrl(IRedirectUrlService redirectUrlService, ILogger logger, IPublishedUrlProvider publishedUrlProvider)
{
_redirectUrlService = redirectUrlService;
_logger = logger;
_umbracoContextAccessor = umbracoContextAccessor;
_publishedUrlProvider = publishedUrlProvider;
}
/// <summary>
@@ -47,7 +47,7 @@ namespace Umbraco.Web.Routing
}
var content = frequest.UmbracoContext.Content.GetById(redirectUrl.ContentId);
var url = content == null ? "#" : content.Url(_umbracoContextAccessor.UmbracoContext.UrlProvider, redirectUrl.Culture);
var url = content == null ? "#" : content.Url(_publishedUrlProvider, redirectUrl.Culture);
if (url.StartsWith("#"))
{
_logger.Debug<ContentFinderByRedirectUrl>("Route {Route} matches content {ContentId} which has no url.", route, redirectUrl.ContentId);
@@ -1,5 +1,4 @@
using System;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
@@ -10,17 +9,17 @@ namespace Umbraco.Web.Routing
/// </summary>
public class DefaultMediaUrlProvider : IMediaUrlProvider
{
private readonly PropertyEditorCollection _propertyEditors;
private readonly UriUtility _uriUtility;
private readonly MediaUrlGeneratorCollection _mediaPathGenerators;
public DefaultMediaUrlProvider(PropertyEditorCollection propertyEditors, UriUtility uriUtility)
public DefaultMediaUrlProvider(MediaUrlGeneratorCollection mediaPathGenerators, UriUtility uriUtility)
{
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
_mediaPathGenerators = mediaPathGenerators ?? throw new ArgumentNullException(nameof(mediaPathGenerators));
_uriUtility = uriUtility;
}
/// <inheritdoc />
public virtual UrlInfo GetMediaUrl(IUmbracoContext umbracoContext, IPublishedContent content,
public virtual UrlInfo GetMediaUrl(IPublishedContent content,
string propertyAlias, UrlMode mode, string culture, Uri current)
{
var prop = content.GetProperty(propertyAlias);
@@ -33,25 +32,23 @@ namespace Umbraco.Web.Routing
}
var propType = prop.PropertyType;
string path = null;
if (_propertyEditors.TryGet(propType.EditorAlias, out var editor)
&& editor is IDataEditorWithMediaPath dataEditor)
if (_mediaPathGenerators.TryGetMediaPath(propType.EditorAlias, value, out var path))
{
path = dataEditor.GetMediaPath(value);
var url = AssembleUrl(path, current, mode);
return UrlInfo.Url(url.ToString(), culture);
}
var url = AssembleUrl(path, current, mode);
return url == null ? null : UrlInfo.Url(url.ToString(), culture);
return null;
}
private Uri AssembleUrl(string path, Uri current, UrlMode mode)
{
if (string.IsNullOrEmpty(path))
return null;
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentException($"{nameof(path)} cannot be null or whitespace", nameof(path));
// the stored path is absolute so we just return it as is
if(Uri.IsWellFormedUriString(path, UriKind.Absolute))
if (Uri.IsWellFormedUriString(path, UriKind.Absolute))
return new Uri(path);
Uri uri;
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
@@ -17,24 +16,27 @@ namespace Umbraco.Web.Routing
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
private readonly ISiteDomainHelper _siteDomainHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly UriUtility _uriUtility;
public DefaultUrlProvider(IRequestHandlerSection requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility)
public DefaultUrlProvider(IRequestHandlerSection requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility)
{
_requestSettings = requestSettings;
_logger = logger;
_globalSettings = globalSettings;
_siteDomainHelper = siteDomainHelper;
_uriUtility = uriUtility;
_umbracoContextAccessor = umbracoContextAccessor;
}
#region GetUrl
/// <inheritdoc />
public virtual UrlInfo GetUrl(IUmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current)
public virtual UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string culture, Uri current)
{
if (!current.IsAbsoluteUri) throw new ArgumentException("Current url must be absolute.", nameof(current));
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
// will not use cache if previewing
var route = umbracoContext.Content.GetRouteById(content.Id, culture);
@@ -70,7 +72,7 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Gets the other urls of a published content.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="umbracoContextAccessor">The Umbraco context.</param>
/// <param name="id">The published content id.</param>
/// <param name="current">The current absolute url.</param>
/// <returns>The other urls for the published content.</returns>
@@ -78,8 +80,9 @@ namespace Umbraco.Web.Routing
/// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
/// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
/// </remarks>
public virtual IEnumerable<UrlInfo> GetOtherUrls(IUmbracoContext umbracoContext, int id, Uri current)
public virtual IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current)
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
var node = umbracoContext.Content.GetById(id);
if (node == null)
yield break;
@@ -344,7 +344,7 @@ namespace Umbraco.Web.Routing
/// <param name="rootNodeId">The current domain root node identifier, or null.</param>
/// <returns>The deepest wildcard Domain in the path, or null.</returns>
/// <remarks>Looks _under_ rootNodeId but not _at_ rootNodeId.</remarks>
internal static Domain FindWildcardDomainInPath(IEnumerable<Domain> domains, string path, int? rootNodeId)
public static Domain FindWildcardDomainInPath(IEnumerable<Domain> domains, string path, int? rootNodeId)
{
var stopNodeId = rootNodeId ?? -1;
@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Web.Routing
{
/// <summary>
@@ -11,7 +12,6 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Gets the url of a media item.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="content">The published content.</param>
/// <param name="propertyAlias">The property alias to resolve the url from.</param>
/// <param name="mode">The url mode.</param>
@@ -26,6 +26,6 @@ namespace Umbraco.Web.Routing
/// e.g. a cdn url provider will most likely always return an absolute url.</para>
/// <para>If the provider is unable to provide a url, it returns <c>null</c>.</para>
/// </remarks>
UrlInfo GetMediaUrl(IUmbracoContext umbracoContext, IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current);
UrlInfo GetMediaUrl(IPublishedContent content, string propertyAlias, UrlMode mode, string culture, Uri current);
}
}
@@ -12,7 +12,6 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Gets the url of a published content.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="content">The published content.</param>
/// <param name="mode">The url mode.</param>
/// <param name="culture">A culture.</param>
@@ -24,12 +23,11 @@ namespace Umbraco.Web.Routing
/// when no culture is specified, the current culture.</para>
/// <para>If the provider is unable to provide a url, it should return <c>null</c>.</para>
/// </remarks>
UrlInfo GetUrl(IUmbracoContext umbracoContext, IPublishedContent content, UrlMode mode, string culture, Uri current);
UrlInfo GetUrl(IPublishedContent content, UrlMode mode, string culture, Uri current);
/// <summary>
/// Gets the other urls of a published content.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="id">The published content id.</param>
/// <param name="current">The current absolute url.</param>
/// <returns>The other urls for the published content.</returns>
@@ -37,6 +35,6 @@ namespace Umbraco.Web.Routing
/// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
/// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
/// </remarks>
IEnumerable<UrlInfo> GetOtherUrls(IUmbracoContext umbracoContext, int id, Uri current);
IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current);
}
}
+16 -32
View File
@@ -16,18 +16,19 @@ namespace Umbraco.Web.Routing
#region Ctor and configuration
/// <summary>
/// InitialiIUrlProviderzes a new instance of the <see cref="UrlProvider"/> class with an Umbraco context and a list of url providers.
/// Initializes a new instance of the <see cref="UrlProvider"/> class with an Umbraco context and a list of url providers.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="umbracoContextAccessor">The Umbraco context accessor.</param>
/// <param name="routingSettings">Routing settings.</param>
/// <param name="urlProviders">The list of url providers.</param>
/// <param name="mediaUrlProviders">The list of media url providers.</param>
/// <param name="variationContextAccessor">The current variation accessor.</param>
public UrlProvider(IUmbracoContext umbracoContext, IWebRoutingSection routingSettings, IEnumerable<IUrlProvider> urlProviders, IEnumerable<IMediaUrlProvider> mediaUrlProviders, IVariationContextAccessor variationContextAccessor)
/// <param name="propertyEditorCollection"></param>
public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IWebRoutingSection routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor)
{
if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings));
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_urlProviders = urlProviders;
_mediaUrlProviders = mediaUrlProviders;
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
@@ -40,25 +41,8 @@ namespace Umbraco.Web.Routing
}
}
/// <summary>
/// Initializes a new instance of the <see cref="UrlProvider"/> class with an Umbraco context and a list of url providers.
/// </summary>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="urlProviders">The list of url providers.</param>
/// <param name="mediaUrlProviders">The list of media url providers</param>
/// <param name="variationContextAccessor">The current variation accessor.</param>
/// <param name="mode">An optional provider mode.</param>
public UrlProvider(IUmbracoContext umbracoContext, IEnumerable<IUrlProvider> urlProviders, IEnumerable<IMediaUrlProvider> mediaUrlProviders, IVariationContextAccessor variationContextAccessor, UrlMode mode = UrlMode.Auto)
{
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_urlProviders = urlProviders;
_mediaUrlProviders = mediaUrlProviders;
_variationContextAccessor = variationContextAccessor;
Mode = mode;
}
private readonly IUmbracoContext _umbracoContext;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IEnumerable<IUrlProvider> _urlProviders;
private readonly IEnumerable<IMediaUrlProvider> _mediaUrlProviders;
private readonly IVariationContextAccessor _variationContextAccessor;
@@ -72,9 +56,9 @@ namespace Umbraco.Web.Routing
#region GetUrl
private IPublishedContent GetDocument(int id) => _umbracoContext.Content.GetById(id);
private IPublishedContent GetDocument(Guid id) => _umbracoContext.Content.GetById(id);
private IPublishedContent GetMedia(Guid id) => _umbracoContext.Media.GetById(id);
private IPublishedContent GetDocument(int id) => _umbracoContextAccessor.UmbracoContext.Content.GetById(id);
private IPublishedContent GetDocument(Guid id) => _umbracoContextAccessor.UmbracoContext.Content.GetById(id);
private IPublishedContent GetMedia(Guid id) => _umbracoContextAccessor.UmbracoContext.Media.GetById(id);
/// <summary>
/// Gets the url of a published content.
@@ -130,9 +114,9 @@ namespace Umbraco.Web.Routing
}
if (current == null)
current = _umbracoContext.CleanedUmbracoUrl;
current = _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl;
var url = _urlProviders.Select(provider => provider.GetUrl(_umbracoContext, content, mode, culture, current))
var url = _urlProviders.Select(provider => provider.GetUrl(content, mode, culture, current))
.FirstOrDefault(u => u != null);
return url?.Text ?? "#"; // legacy wants this
}
@@ -142,7 +126,7 @@ namespace Umbraco.Web.Routing
var provider = _urlProviders.OfType<DefaultUrlProvider>().FirstOrDefault();
var url = provider == null
? route // what else?
: provider.GetUrlFromRoute(route, _umbracoContext, id, _umbracoContext.CleanedUmbracoUrl, Mode, culture)?.Text;
: provider.GetUrlFromRoute(route, _umbracoContextAccessor.UmbracoContext, id, _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl, Mode, culture)?.Text;
return url ?? "#";
}
@@ -162,7 +146,7 @@ namespace Umbraco.Web.Routing
/// </remarks>
public IEnumerable<UrlInfo> GetOtherUrls(int id)
{
return GetOtherUrls(id, _umbracoContext.CleanedUmbracoUrl);
return GetOtherUrls(id, _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl);
}
/// <summary>
@@ -177,7 +161,7 @@ namespace Umbraco.Web.Routing
/// </remarks>
public IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current)
{
return _urlProviders.SelectMany(provider => provider.GetOtherUrls(_umbracoContext, id, current) ?? Enumerable.Empty<UrlInfo>());
return _urlProviders.SelectMany(provider => provider.GetOtherUrls(id, current) ?? Enumerable.Empty<UrlInfo>());
}
#endregion
@@ -231,10 +215,10 @@ namespace Umbraco.Web.Routing
}
if (current == null)
current = _umbracoContext.CleanedUmbracoUrl;
current = _umbracoContextAccessor.UmbracoContext.CleanedUmbracoUrl;
var url = _mediaUrlProviders.Select(provider =>
provider.GetMediaUrl(_umbracoContext, content, propertyAlias, mode, culture, current))
provider.GetMediaUrl(content, propertyAlias, mode, culture, current))
.FirstOrDefault(u => u != null);
return url?.Text ?? "";
@@ -26,7 +26,8 @@ namespace Umbraco.Web.Routing
IContentService contentService,
IVariationContextAccessor variationContextAccessor,
ILogger logger,
UriUtility uriUtility)
UriUtility uriUtility,
IPublishedUrlProvider publishedUrlProvider)
{
if (content == null) throw new ArgumentNullException(nameof(content));
if (publishedRouter == null) throw new ArgumentNullException(nameof(publishedRouter));
@@ -35,6 +36,7 @@ namespace Umbraco.Web.Routing
if (textService == null) throw new ArgumentNullException(nameof(textService));
if (contentService == null) throw new ArgumentNullException(nameof(contentService));
if (logger == null) throw new ArgumentNullException(nameof(logger));
if (publishedUrlProvider == null) throw new ArgumentNullException(nameof(publishedUrlProvider));
if (uriUtility == null) throw new ArgumentNullException(nameof(uriUtility));
if (variationContextAccessor == null) throw new ArgumentNullException(nameof(variationContextAccessor));
@@ -61,7 +63,7 @@ namespace Umbraco.Web.Routing
//get all URLs for all cultures
//in a HashSet, so de-duplicates too
foreach (var cultureUrl in GetContentUrlsByCulture(content, cultures, publishedRouter, umbracoContext, contentService, textService, variationContextAccessor, logger, uriUtility))
foreach (var cultureUrl in GetContentUrlsByCulture(content, cultures, publishedRouter, umbracoContext, contentService, textService, variationContextAccessor, logger, uriUtility, publishedUrlProvider))
{
urls.Add(cultureUrl);
}
@@ -79,7 +81,7 @@ namespace Umbraco.Web.Routing
// get the 'other' urls - ie not what you'd get with GetUrl() but urls that would route to the document, nevertheless.
// for these 'other' urls, we don't check whether they are routable, collide, anything - we just report them.
foreach (var otherUrl in umbracoContext.UrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text).ThenBy(x => x.Culture))
foreach (var otherUrl in publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text).ThenBy(x => x.Culture))
if (urls.Add(otherUrl)) //avoid duplicates
yield return otherUrl;
}
@@ -103,7 +105,8 @@ namespace Umbraco.Web.Routing
ILocalizedTextService textService,
IVariationContextAccessor variationContextAccessor,
ILogger logger,
UriUtility uriUtility)
UriUtility uriUtility,
IPublishedUrlProvider publishedUrlProvider)
{
foreach (var culture in cultures)
{
@@ -116,7 +119,7 @@ namespace Umbraco.Web.Routing
string url;
try
{
url = umbracoContext.UrlProvider.GetUrl(content.Id, culture: culture);
url = publishedUrlProvider.GetUrl(content.Id, culture: culture);
}
catch (Exception ex)
{
@@ -9,7 +9,7 @@ using Umbraco.Core.Sync;
namespace Umbraco.Web.Scheduling
{
internal class KeepAlive : RecurringTaskBase
public class KeepAlive : RecurringTaskBase
{
private readonly IRuntimeState _runtime;
private readonly IKeepAliveSection _keepAliveSection;
@@ -10,7 +10,7 @@ namespace Umbraco.Web.Scheduling
/// <summary>
/// Used to cleanup temporary file locations
/// </summary>
internal class TempFileCleanup : RecurringTaskBase
public class TempFileCleanup : RecurringTaskBase
{
private readonly DirectoryInfo[] _tempFolders;
private readonly TimeSpan _age;
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Sync
{
public interface IBatchedDatabaseServerMessenger : IServerMessenger
{
void FlushBatch();
}
}
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Umbraco.Core;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Templates
{
@@ -13,10 +14,11 @@ namespace Umbraco.Web.Templates
this._getMediaUrl = getMediaUrl;
}
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public HtmlImageSourceParser(IUmbracoContextAccessor umbracoContextAccessor)
private readonly IPublishedUrlProvider _publishedUrlProvider;
public HtmlImageSourceParser(IPublishedUrlProvider publishedUrlProvider)
{
_umbracoContextAccessor = umbracoContextAccessor;
_publishedUrlProvider = publishedUrlProvider;
}
private static readonly Regex ResolveImgPattern = new Regex(@"(<img[^>]*src="")([^""\?]*)((?:\?[^""]*)?""[^>]*data-udi="")([^""]*)(""[^>]*>)",
@@ -54,7 +56,7 @@ namespace Umbraco.Web.Templates
public string EnsureImageSources(string text)
{
if(_getMediaUrl == null)
_getMediaUrl = (guid) => _umbracoContextAccessor.UmbracoContext.UrlProvider.GetMediaUrl(guid);
_getMediaUrl = (guid) => _publishedUrlProvider.GetMediaUrl(guid);
return ResolveImgPattern.Replace(text, match =>
{
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Templates
@@ -18,10 +16,12 @@ namespace Umbraco.Web.Templates
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IPublishedUrlProvider _publishedUrlProvider;
public HtmlLocalLinkParser(IUmbracoContextAccessor umbracoContextAccessor)
public HtmlLocalLinkParser(IUmbracoContextAccessor umbracoContextAccessor, IPublishedUrlProvider publishedUrlProvider)
{
_umbracoContextAccessor = umbracoContextAccessor;
_publishedUrlProvider = publishedUrlProvider;
}
internal IEnumerable<Udi> FindUdisFromLocalLinks(string text)
@@ -64,7 +64,6 @@ namespace Umbraco.Web.Templates
if (_umbracoContextAccessor.UmbracoContext == null)
throw new InvalidOperationException("Could not parse internal links, there is no current UmbracoContext");
var urlProvider = _umbracoContextAccessor.UmbracoContext.UrlProvider;
foreach((int? intId, GuidUdi udi, string tagValue) in FindLocalLinkIds(text))
{
@@ -72,9 +71,9 @@ namespace Umbraco.Web.Templates
{
var newLink = "#";
if (udi.EntityType == Constants.UdiEntityType.Document)
newLink = urlProvider.GetUrl(udi.Guid);
newLink = _publishedUrlProvider.GetUrl(udi.Guid);
else if (udi.EntityType == Constants.UdiEntityType.Media)
newLink = urlProvider.GetMediaUrl(udi.Guid);
newLink = _publishedUrlProvider.GetMediaUrl(udi.Guid);
if (newLink == null)
newLink = "#";
@@ -83,7 +82,7 @@ namespace Umbraco.Web.Templates
}
else if (intId.HasValue)
{
var newLink = urlProvider.GetUrl(intId.Value);
var newLink = _publishedUrlProvider.GetUrl(intId.Value);
text = text.Replace(tagValue, "href=\"" + newLink);
}
}
@@ -0,0 +1,9 @@
using Umbraco.Web.Models.Trees;
namespace Umbraco.Web.Trees
{
public interface IMenuItemCollectionFactory
{
MenuItemCollection Create();
}
}
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Web.Actions;
namespace Umbraco.Web.Models.Trees
{
@@ -9,17 +10,16 @@ namespace Umbraco.Web.Models.Trees
[DataContract(Name = "menuItems", Namespace = "")]
public class MenuItemCollection
{
public static MenuItemCollection Empty => new MenuItemCollection();
private readonly MenuItemList _menuItems;
private readonly MenuItemList _menuItems = new MenuItemList();
public MenuItemCollection()
public MenuItemCollection(ActionCollection actionCollection)
{
_menuItems = new MenuItemList(actionCollection);
}
public MenuItemCollection(IEnumerable<MenuItem> items)
public MenuItemCollection(ActionCollection actionCollection, IEnumerable<MenuItem> items)
{
_menuItems = new MenuItemList(items);
_menuItems = new MenuItemList(actionCollection, items);
}
/// <summary>
@@ -0,0 +1,21 @@
using Umbraco.Web.Actions;
using Umbraco.Web.Models.Trees;
namespace Umbraco.Web.Trees
{
public class MenuItemCollectionFactory: IMenuItemCollectionFactory
{
private readonly ActionCollection _actionCollection;
public MenuItemCollectionFactory(ActionCollection actionCollection)
{
_actionCollection = actionCollection;
}
public MenuItemCollection Create()
{
return new MenuItemCollection(_actionCollection);
}
}
}
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using Umbraco.Core.Services;
using Umbraco.Web.Actions;
using Umbraco.Web.Composing;
namespace Umbraco.Web.Models.Trees
{
@@ -13,13 +12,17 @@ namespace Umbraco.Web.Models.Trees
/// </remarks>
public class MenuItemList : List<MenuItem>
{
public MenuItemList()
private readonly ActionCollection _actionCollection;
public MenuItemList(ActionCollection actionCollection)
{
_actionCollection = actionCollection;
}
public MenuItemList( IEnumerable<MenuItem> items)
public MenuItemList(ActionCollection actionCollection, IEnumerable<MenuItem> items)
: base(items)
{
_actionCollection = actionCollection;
}
/// <summary>
@@ -44,7 +47,7 @@ namespace Umbraco.Web.Models.Trees
private MenuItem CreateMenuItem<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
where T : IAction
{
var item = Current.Actions.GetAction<T>();
var item = _actionCollection.GetAction<T>();
if (item == null) return null;
var menuItem = new MenuItem(item, textService.Localize($"actions/{item.Alias}"))
@@ -24,9 +24,4 @@
<_Parameter1>Umbraco.Tests.Benchmarks</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<Folder Include="Logging\Viewer" />
</ItemGroup>
</Project>
@@ -22,9 +22,9 @@ namespace Umbraco.Web
/// </summary>
internal UmbracoContextReference(IUmbracoContext umbracoContext, bool isRoot, IUmbracoContextAccessor umbracoContextAccessor)
{
UmbracoContext = umbracoContext;
IsRoot = isRoot;
UmbracoContext = umbracoContext;
_umbracoContextAccessor = umbracoContextAccessor;
}
+10
View File
@@ -0,0 +1,10 @@
using System;
using Umbraco.Web.Routing;
namespace Umbraco.Core
{
public interface IUmbracoRouteEventSender
{
event EventHandler<RoutableAttemptEventArgs> RouteAttempt;
}
}
+1 -6
View File
@@ -7,11 +7,6 @@ namespace Umbraco.Core.Configuration
{
public class ConfigsFactory : IConfigsFactory
{
public ConfigsFactory()
{
}
public IHostingSettings HostingSettings { get; } = new HostingSettings();
public ICoreDebug CoreDebug { get; } = new CoreDebug();
@@ -32,7 +27,7 @@ namespace Umbraco.Core.Configuration
configs.AddPasswordConfigurations();
configs.Add(() => CoreDebug);
configs.Add<IConnectionStrings>(() => new ConnectionStrings());
configs.Add<IConnectionStrings>(() => new ConnectionStrings(ioHelper));
configs.AddCoreConfigs(ioHelper);
return configs;
}
@@ -8,6 +8,13 @@ namespace Umbraco.Core.Configuration
{
public class ConnectionStrings : IConnectionStrings
{
private readonly IIOHelper _ioHelper;
public ConnectionStrings(IIOHelper ioHelper)
{
_ioHelper = ioHelper;
}
public ConfigConnectionString this[string key]
{
get
@@ -17,5 +24,22 @@ namespace Umbraco.Core.Configuration
return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
}
}
public void RemoveConnectionString(string key)
{
var fileName = _ioHelper.MapPath(string.Format("{0}/web.config", _ioHelper.Root));
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
if (setting != null)
{
setting.Remove();
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
}
var settings = ConfigurationManager.ConnectionStrings[key];
}
}
}
+1 -21
View File
@@ -254,27 +254,7 @@ namespace Umbraco.Core.Configuration
ConfigurationManager.RefreshSection("appSettings");
}
/// <summary>
/// Removes a setting from the configuration file.
/// </summary>
/// <param name="key">Key of the setting to be removed.</param>
public static void RemoveSetting(string key, IIOHelper ioHelper)
{
var fileName = ioHelper.MapPath(string.Format("{0}/web.config", ioHelper.Root));
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
var setting = appSettings.Descendants("add").FirstOrDefault(s => s.Attribute("key").Value == key);
if (setting != null)
{
setting.Remove();
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
}
}
/// <summary>
/// Gets the time out in minutes.
/// </summary>
@@ -9,6 +9,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Persistence;
using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Examine
@@ -17,19 +18,19 @@ namespace Umbraco.Examine
{
private readonly IExamineManager _examineManager;
private readonly ILocalizationService _languageService;
private readonly ICurrentUserAccessor _currentUserAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IEntityService _entityService;
private readonly IUmbracoTreeSearcherFields _treeSearcherFields;
public BackOfficeExamineSearcher(IExamineManager examineManager,
ILocalizationService languageService,
ICurrentUserAccessor currentUserAccessor,
IUmbracoContextAccessor umbracoContextAccessor,
IEntityService entityService,
IUmbracoTreeSearcherFields treeSearcherFields)
{
_examineManager = examineManager;
_languageService = languageService;
_currentUserAccessor = currentUserAccessor;
_umbracoContextAccessor = umbracoContextAccessor;
_entityService = entityService;
_treeSearcherFields = treeSearcherFields;
}
@@ -48,7 +49,7 @@ namespace Umbraco.Examine
query = "\"" + g.ToString() + "\"";
}
var currentUser = _currentUserAccessor.TryGetCurrentUser();
var currentUser = _umbracoContextAccessor.UmbracoContext?.Security?.CurrentUser;
switch (entityType)
{
@@ -26,7 +26,6 @@
<ItemGroup>
<ProjectReference Include="..\Umbraco.Abstractions\Umbraco.Abstractions.csproj" />
<ProjectReference Include="..\Umbraco.Examine\Umbraco.Examine.csproj" />
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" />
</ItemGroup>
@@ -12,7 +12,6 @@
<ItemGroup>
<ProjectReference Include="..\Umbraco.Abstractions\Umbraco.Abstractions.csproj" />
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" />
</ItemGroup>
</Project>
@@ -4,10 +4,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Serialization;
namespace Umbraco.Web.Cache
{

Some files were not shown because too many files have changed in this diff Show More