Merge branch 'netcore/dev' into netcore/77007-replace-no-nodes

# Conflicts:
#	src/Umbraco.Core/Configuration/IGlobalSettings.cs
#	src/Umbraco.Core/Constants-Web.cs
This commit is contained in:
Andy Butland
2020-03-06 07:28:13 +01:00
328 changed files with 2537 additions and 2053 deletions
+2
View File
@@ -43,6 +43,8 @@ If you only see a build.bat-file, you're probably on the wrong branch. If you sw
You might run into [Powershell quirks](#powershell-quirks).
If it runs without errors; Hooray! Now you can continue with [the next step](CONTRIBUTING.md#how-do-i-begin) and open the solution and build it.
### Build Infrastructure
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
+2 -2
View File
@@ -28,7 +28,7 @@ This project and everyone participating in it, is governed by the [our Code of C
[Working with the code](#working-with-the-code)
* [Building Umbraco from source code](#building-umbraco-from-source-code)
* [Working with the source code](#working-with-the-source-code)
* [Making changes after the PR was opened](#making-changes-after-the-pr-was-opened)
* [Making changes after the PR is open](#making-changes-after-the-pr-is-open)
* [Which branch should I target for my contributions?](#which-branch-should-i-target-for-my-contributions)
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
@@ -65,7 +65,7 @@ Great question! The short version goes like this:
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
* **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v8/contrib`, create a new branch first.
* **Push** - great, now you can push the changes up to your fork on GitHub
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here] (https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here](https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
![Create a pull request](img/createpullrequest.png)
@@ -0,0 +1,15 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class ActiveDirectorySettings : IActiveDirectorySettings
{
public ActiveDirectorySettings()
{
ActiveDirectoryDomain = ConfigurationManager.AppSettings["ActiveDirectoryDomain"];
}
public string ActiveDirectoryDomain { get; }
}
}
@@ -1,4 +1,5 @@
using System.Configuration;
using Umbraco.Configuration;
using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
@@ -10,6 +11,13 @@ namespace Umbraco.Core.Configuration
public IHostingSettings HostingSettings { get; } = new HostingSettings();
public ICoreDebug CoreDebug { get; } = new CoreDebug();
public IMachineKeyConfig MachineKeyConfig { get; } = new MachineKeyConfig();
public IIndexCreatorSettings IndexCreatorSettings { get; } = new IndexCreatorSettings();
public INuCacheSettings NuCacheSettings { get; } = new NuCacheSettings();
public ITypeFinderSettings TypeFinderSettings { get; } = new TypeFinderSettings();
public IRuntimeSettings RuntimeSettings { get; } = new RuntimeSettings();
public IActiveDirectorySettings ActiveDirectorySettings { get; } = new ActiveDirectorySettings();
public IExceptionFilterSettings ExceptionFilterSettings { get; } = new ExceptionFilterSettings();
public IUmbracoSettingsSection UmbracoSettings { get; }
@@ -27,7 +35,18 @@ namespace Umbraco.Core.Configuration
configs.AddPasswordConfigurations();
configs.Add(() => CoreDebug);
configs.Add(() => MachineKeyConfig);
configs.Add<IConnectionStrings>(() => new ConnectionStrings(ioHelper));
configs.Add<IModelsBuilderConfig>(() => new ModelsBuilderConfig(ioHelper));
configs.Add<IIndexCreatorSettings>(() => IndexCreatorSettings);
configs.Add<INuCacheSettings>(() => NuCacheSettings);
configs.Add<ITypeFinderSettings>(() => TypeFinderSettings);
configs.Add<IRuntimeSettings>(() => RuntimeSettings);
configs.Add<IActiveDirectorySettings>(() => ActiveDirectorySettings);
configs.Add<IExceptionFilterSettings>(() => ExceptionFilterSettings);
configs.AddCoreConfigs(ioHelper);
return configs;
}
@@ -0,0 +1,18 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class ExceptionFilterSettings : IExceptionFilterSettings
{
public ExceptionFilterSettings()
{
if (bool.TryParse(ConfigurationManager.AppSettings["Umbraco.Web.DisableModelBindingExceptionFilter"],
out var disabled))
{
Disabled = disabled;
}
}
public bool Disabled { get; }
}
}
@@ -382,6 +382,10 @@ namespace Umbraco.Core.Configuration
private string _databaseFactoryServerVersion;
public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion);
private string _mainDomLock;
public string MainDomLock => GetterWithDefaultValue(Constants.AppSettings.MainDomLock, string.Empty, ref _mainDomLock);
private T GetterWithDefaultValue<T>(string appSettingKey, T defaultValue, ref T backingField)
{
if (backingField != null) return backingField;
@@ -0,0 +1,15 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class IndexCreatorSettings : IIndexCreatorSettings
{
public IndexCreatorSettings()
{
LuceneDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
}
public string LuceneDirectoryFactory { get; }
}
}
@@ -0,0 +1,20 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class MachineKeyConfig : IMachineKeyConfig
{
//TODO all the machineKey stuff should be replaced: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/compatibility/replacing-machinekey?view=aspnetcore-3.1
public bool HasMachineKey
{
get
{
var machineKeySection =
ConfigurationManager.GetSection("system.web/machineKey") as ConfigurationSection;
return !(machineKeySection?.ElementInformation?.Source is null);
}
}
}
}
@@ -2,11 +2,11 @@
using System.Configuration;
using System.IO;
using System.Threading;
using System.Web.Configuration;
using Umbraco.Core.Configuration;
using Umbraco.Core;
using Umbraco.Core.IO;
namespace Umbraco.ModelsBuilder.Embedded.Configuration
namespace Umbraco.Configuration
{
/// <summary>
/// Represents the models builder configuration.
@@ -21,7 +21,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
private object _flagOutOfDateModelsLock;
private bool _flagOutOfDateModelsConfigured;
private bool _flagOutOfDateModels;
public const string DefaultModelsNamespace = "Umbraco.Web.PublishedModels";
public string DefaultModelsDirectory => _ioHelper.MapPath("~/App_Data/Models");
@@ -37,7 +37,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
Enable = ConfigurationManager.AppSettings[Prefix + "Enable"] == "true";
// ensure defaults are initialized for tests
ModelsNamespace = DefaultModelsNamespace;
ModelsNamespace = Constants.ModelsBuilder.DefaultModelsNamespace;
ModelsDirectory = DefaultModelsDirectory;
DebugLevel = 0;
@@ -95,7 +95,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
Enable = enable;
_modelsMode = modelsMode;
ModelsNamespace = string.IsNullOrWhiteSpace(modelsNamespace) ? DefaultModelsNamespace : modelsNamespace;
ModelsNamespace = string.IsNullOrWhiteSpace(modelsNamespace) ? Constants.ModelsBuilder.DefaultModelsNamespace : modelsNamespace;
EnableFactory = enableFactory;
_flagOutOfDateModels = flagOutOfDateModels;
ModelsDirectory = string.IsNullOrWhiteSpace(modelsDirectory) ? DefaultModelsDirectory : modelsDirectory;
@@ -174,8 +174,13 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration
{
get
{
var section = (CompilationSection)ConfigurationManager.GetSection("system.web/compilation");
return section != null && section.Debug;
if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection section &&
bool.TryParse(section.ElementInformation.Properties["debug"].Value.ToString(), out var isDebug))
{
return isDebug;
}
return false;
}
}
@@ -0,0 +1,14 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class NuCacheSettings : INuCacheSettings
{
public NuCacheSettings()
{
BTreeBlockSize = ConfigurationManager.AppSettings["Umbraco.Web.PublishedCache.NuCache.BTree.BlockSize"];
}
public string BTreeBlockSize { get; }
}
}
@@ -0,0 +1,29 @@
using System.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
public class RuntimeSettings : IRuntimeSettings
{
public RuntimeSettings()
{
if (ConfigurationManager.GetSection("system.web/httpRuntime") is ConfigurationSection section)
{
var maxRequestLengthProperty = section.ElementInformation.Properties["maxRequestLength"];
if (maxRequestLengthProperty != null && maxRequestLengthProperty.Value is int requestLength)
{
MaxRequestLength = requestLength;
}
var maxQueryStringProperty = section.ElementInformation.Properties["maxQueryStringLength"];
if (maxQueryStringProperty != null && maxQueryStringProperty.Value is int maxQueryStringLength)
{
MaxQueryStringLength = maxQueryStringLength;
}
}
}
public int? MaxQueryStringLength { get; }
public int? MaxRequestLength { get; }
}
}
@@ -0,0 +1,17 @@
using System.Configuration;
using Umbraco.Core.Configuration;
using Umbraco.Core;
namespace Umbraco.Configuration
{
public class TypeFinderSettings : ITypeFinderSettings
{
public TypeFinderSettings()
{
AssembliesAcceptingLoadExceptions = ConfigurationManager.AppSettings[
Constants.AppSettings.AssembliesAcceptingLoadExceptions];
}
public string AssembliesAcceptingLoadExceptions { get; }
}
}
@@ -53,7 +53,7 @@ namespace Umbraco.Web.Cache
{
macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey<IMacro>(payload.Id));
}
};
}
base.Refresh(json);
}
+1 -1
View File
@@ -126,7 +126,7 @@ namespace Umbraco.Core.Collections
if (_items.TryGetValue(key, out value))
yield return value;
else if (throwOnMissing)
throw new Exception(MissingDependencyError);
throw new Exception($"{MissingDependencyError} Error in type {typeof(TItem).Name}, with key {key}");
}
}
}
@@ -79,9 +79,12 @@ namespace Umbraco.Core.Composing
foreach (var type in types)
EnsureType(type, "register");
// register them
// register them - ensuring that each item is registered with the same lifetime as the collection.
// NOTE: Previously each one was not registered with the same lifetime which would mean that if there
// was a dependency on an individual item, it would resolve a brand new transient instance which isn't what
// we would expect to happen. The same item should be resolved from the container as the collection.
foreach (var type in types)
register.Register(type);
register.Register(type, CollectionLifetime);
_registeredTypes = types;
}
@@ -13,13 +13,13 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
Group = "Configuration")]
public class TrySkipIisCustomErrorsCheck : AbstractConfigCheck
{
private readonly IHostingEnvironment _hostingEnvironment;
private readonly Version _iisVersion;
public TrySkipIisCustomErrorsCheck(ILocalizedTextService textService, IIOHelper ioHelper, ILogger logger,
IHostingEnvironment hostingEnvironment)
: base(textService, ioHelper, logger)
{
_hostingEnvironment = hostingEnvironment;
_iisVersion = hostingEnvironment.IISVersion;
}
public override string FilePath => "~/Config/umbracoSettings.config";
@@ -33,7 +33,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
get
{
// beware! 7.5 and 7.5.0 are not the same thing!
var recommendedValue = _hostingEnvironment.IISVersion >= new Version("7.5")
var recommendedValue = _iisVersion >= new Version("7.5")
? bool.TrueString.ToLower()
: bool.FalseString.ToLower();
return new List<AcceptableConfiguration> { new AcceptableConfiguration { IsRecommended = true, Value = recommendedValue } };
@@ -45,7 +45,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
get
{
return TextService.Localize("healthcheck/trySkipIisCustomErrorsCheckSuccessMessage",
new[] { Values.First(v => v.IsRecommended).Value, _hostingEnvironment.IISVersion.ToString() });
new[] { Values.First(v => v.IsRecommended).Value, _iisVersion.ToString() });
}
}
@@ -54,7 +54,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
get
{
return TextService.Localize("healthcheck/trySkipIisCustomErrorsCheckErrorMessage",
new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, _hostingEnvironment.IISVersion.ToString() });
new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, _iisVersion.ToString() });
}
}
@@ -63,7 +63,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
get
{
return TextService.Localize("healthcheck/trySkipIisCustomErrorsCheckRectifySuccessMessage",
new[] { Values.First(v => v.IsRecommended).Value, _hostingEnvironment.IISVersion.ToString() });
new[] { Values.First(v => v.IsRecommended).Value, _iisVersion.ToString() });
}
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface IActiveDirectorySettings
{
string ActiveDirectoryDomain { get; }
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface IExceptionFilterSettings
{
bool Disabled { get; }
}
}
@@ -95,6 +95,7 @@
bool DisableElectionForSingleServer { get; }
string RegisterType { get; }
string DatabaseFactoryServerVersion { get; }
string MainDomLock { get; }
/// <summary>
/// Gets the path to the razor file used when no published content is available.
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface IIndexCreatorSettings
{
string LuceneDirectoryFactory { get; }
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface IMachineKeyConfig
{
bool HasMachineKey { get;}
}
}
@@ -1,4 +1,4 @@
namespace Umbraco.ModelsBuilder.Embedded.Configuration
namespace Umbraco.Core.Configuration
{
public interface IModelsBuilderConfig
{
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface INuCacheSettings
{
string BTreeBlockSize { get; }
}
}
@@ -0,0 +1,8 @@
namespace Umbraco.Core.Configuration
{
public interface IRuntimeSettings
{
int? MaxQueryStringLength { get; }
int? MaxRequestLength { get; }
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Configuration
{
public interface ITypeFinderSettings
{
string AssembliesAcceptingLoadExceptions { get; }
}
}
@@ -1,4 +1,4 @@
namespace Umbraco.ModelsBuilder.Embedded.Configuration
namespace Umbraco.Core.Configuration
{
/// <summary>
/// Defines the models generation modes.
@@ -8,7 +8,7 @@
/// <summary>
/// Do not generate models.
/// </summary>
Nothing = 0, // default value
Nothing = 0, // default value
/// <summary>
/// Generate models in memory.
@@ -1,4 +1,6 @@
namespace Umbraco.ModelsBuilder.Embedded.Configuration
using Umbraco.Core.Configuration;
namespace Umbraco.Configuration
{
/// <summary>
/// Provides extensions for the <see cref="ModelsMode"/> enumeration.
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
@@ -0,0 +1,17 @@
namespace Umbraco.Core
{
/// <summary>
/// Defines constants.
/// </summary>
public static partial class Constants
{
/// <summary>
/// Defines constants for ModelsBuilder.
/// </summary>
public static class ModelsBuilder
{
public const string DefaultModelsNamespace = "Umbraco.Web.PublishedModels";
}
}
}
@@ -7,4 +7,5 @@ namespace Umbraco.Core.Cookie
void SetCookieValue(string cookieName, string value);
bool HasCookie(string cookieName);
}
}
+1 -1
View File
@@ -41,7 +41,7 @@ namespace Umbraco.Core
public void AddDateTime(DateTime d)
{
_writer.Write(d.Ticks);;
_writer.Write(d.Ticks);
}
public void AddString(string s)
@@ -11,8 +11,6 @@ namespace Umbraco.Core.Hosting
string LocalTempPath { get; }
string ApplicationVirtualPath { get; }
int CurrentDomainId { get; }
bool IsDebugMode { get; }
/// <summary>
/// Gets a value indicating whether Umbraco is hosted.
@@ -22,11 +20,6 @@ namespace Umbraco.Core.Hosting
string MapPath(string path);
string ToAbsolute(string virtualPath, string root);
/// <summary>
/// Terminates the current application. The application restarts the next time a request is received for it.
/// </summary>
void LazyRestartApplication();
void RegisterObject(IRegisteredObject registeredObject);
void UnregisterObject(IRegisteredObject registeredObject);
}
+5 -4
View File
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Net;
namespace Umbraco.Core.Manifest
{
@@ -13,13 +14,13 @@ namespace Umbraco.Core.Manifest
private static volatile bool _isRestarting;
private readonly ILogger _logger;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly List<FileSystemWatcher> _fws = new List<FileSystemWatcher>();
public ManifestWatcher(ILogger logger, IHostingEnvironment hostingEnvironment)
public ManifestWatcher(ILogger logger, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_hostingEnvironment = hostingEnvironment;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
}
public void Start(params string[] packageFolders)
@@ -57,7 +58,7 @@ namespace Umbraco.Core.Manifest
_isRestarting = true;
_logger.Info<ManifestWatcher>("Manifest has changed, app pool is restarting ({Path})", e.FullPath);
_hostingEnvironment.LazyRestartApplication();
_umbracoApplicationLifetime.Restart();
Dispose(); // uh? if the app restarts then this should be disposed anyways?
}
}
@@ -6,7 +6,7 @@ namespace Umbraco.Web.Models
/// <summary>
/// The model used when rendering Partial View Macros
/// </summary>
public class PartialViewMacroModel
public class PartialViewMacroModel : IContentModel
{
public PartialViewMacroModel(IPublishedContent page,
@@ -0,0 +1,14 @@
namespace Umbraco.Net
{
public interface IUmbracoApplicationLifetime
{
/// <summary>
/// A value indicating whether the application is restarting after the current request.
/// </summary>
bool IsRestarting { get; }
/// <summary>
/// Terminates the current application. The application restarts the next time a request is received for it.
/// </summary>
void Restart();
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Net
{
public interface IUserAgentProvider
{
string GetUserAgent();
}
}
@@ -7,7 +7,7 @@ using Umbraco.Core.Services;
namespace Umbraco.Core.Packaging
{
public class ConflictingPackageData
public class ConflictingPackageData
{
private readonly IMacroService _macroService;
private readonly IFileService _fileService;
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Packaging
return stylesheetNodes
.Select(n =>
{
var xElement = n.Element("Name") ?? n.Element("name"); ;
var xElement = n.Element("Name") ?? n.Element("name");
if (xElement == null)
throw new FormatException("Missing \"Name\" element");
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Models.Packaging
/// <remarks>
/// This is used only for conversions and will not 'get' a PackageDefinition from the repository with a valid ID
/// </remarks>
internal static PackageDefinition FromCompiledPackage(CompiledPackage compiled)
public static PackageDefinition FromCompiledPackage(CompiledPackage compiled)
{
return new PackageDefinition
{
@@ -90,7 +90,7 @@ namespace Umbraco.Core.Packaging
{
var packagesXml = EnsureStorage(out _);
if (packagesXml?.Root == null)
yield break;;
yield break;
foreach (var packageXml in packagesXml.Root.Elements("package"))
yield return _parser.ToPackageDefinition(packageXml);
@@ -518,7 +518,6 @@ namespace Umbraco.Core.Packaging
private XElement GetStylesheetXml(string name, bool includeProperties)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(name));
;
var sts = _fileService.GetStylesheetByName(name);
if (sts == null) return null;
var stylesheetXml = new XElement("Stylesheet");
@@ -0,0 +1,13 @@
using System;
using Umbraco.Web.Routing;
namespace Umbraco.Core.Request
{
public interface IRequestAccessor
{
string GetRequestValue(string name);
string GetQueryStringValue(string culture);
event EventHandler<UmbracoRequestEventArgs> EndRequest;
event EventHandler<RoutableAttemptEventArgs> RouteAttempt;
}
}
@@ -4,6 +4,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models.PublishedContent;
using System.Globalization;
using Umbraco.Core.Request;
namespace Umbraco.Web.Routing
{
@@ -16,14 +17,14 @@ namespace Umbraco.Web.Routing
public class ContentFinderByIdPath : IContentFinder
{
private readonly ILogger _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IRequestAccessor _requestAccessor;
private readonly IWebRoutingSection _webRoutingSection;
public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger, IHttpContextAccessor httpContextAccessor)
public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger, IRequestAccessor requestAccessor)
{
_webRoutingSection = webRoutingSection ?? throw new System.ArgumentNullException(nameof(webRoutingSection));
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
_httpContextAccessor = httpContextAccessor;
_requestAccessor = requestAccessor;
}
/// <summary>
@@ -56,12 +57,14 @@ namespace Umbraco.Web.Routing
if (node != null)
{
var httpContext = _httpContextAccessor.GetRequiredHttpContext();
var cultureFromQuerystring = _requestAccessor.GetQueryStringValue("culture");
//if we have a node, check if we have a culture in the query string
if (httpContext.Request.QueryString.ContainsKey("culture"))
if (!string.IsNullOrEmpty(cultureFromQuerystring))
{
//we're assuming it will match a culture, if an invalid one is passed in, an exception will throw (there is no TryGetCultureInfo method), i think this is ok though
frequest.Culture = CultureInfo.GetCultureInfo(httpContext.Request.QueryString["culture"]);
frequest.Culture = CultureInfo.GetCultureInfo(cultureFromQuerystring);
}
frequest.PublishedContent = node;
@@ -1,4 +1,6 @@
namespace Umbraco.Web.Routing
using Umbraco.Core.Request;
namespace Umbraco.Web.Routing
{
/// <summary>
/// This looks up a document by checking for the umbPageId of a request/query string
@@ -9,17 +11,17 @@
/// </remarks>
public class ContentFinderByPageIdQuery : IContentFinder
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IRequestAccessor _requestAccessor;
public ContentFinderByPageIdQuery(IHttpContextAccessor httpContextAccessor)
public ContentFinderByPageIdQuery(IRequestAccessor requestAccessor)
{
_httpContextAccessor = httpContextAccessor;
_requestAccessor = requestAccessor;
}
public bool TryFindContent(IPublishedRequest frequest)
{
int pageId;
if (int.TryParse(_httpContextAccessor.GetRequiredHttpContext().Request["umbPageID"], out pageId))
if (int.TryParse(_requestAccessor.GetRequestValue("umbPageID"), out pageId))
{
var doc = frequest.UmbracoContext.Content.GetById(pageId);
@@ -4,13 +4,12 @@ using System.Threading;
using System.Globalization;
using System.IO;
using Umbraco.Core;
using Umbraco.Web.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Request;
using Umbraco.Core.Services;
using Umbraco.Web.Macros;
using Umbraco.Web.Security;
namespace Umbraco.Web.Routing
@@ -23,13 +22,17 @@ namespace Umbraco.Web.Routing
private readonly IWebRoutingSection _webRoutingSection;
private readonly ContentFinderCollection _contentFinders;
private readonly IContentLastChanceFinder _contentLastChanceFinder;
private readonly ServiceContext _services;
private readonly IProfilingLogger _profilingLogger;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly ILogger _logger;
private readonly IUmbracoSettingsSection _umbracoSettingsSection;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IPublishedUrlProvider _publishedUrlProvider;
private readonly IRequestAccessor _requestAccessor;
private readonly IPublishedValueFallback _publishedValueFallback;
private readonly IPublicAccessChecker _publicAccessChecker;
private readonly IFileService _fileService;
private readonly IContentTypeService _contentTypeService;
private readonly IPublicAccessService _publicAccessService;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedRouter"/> class.
@@ -39,22 +42,30 @@ namespace Umbraco.Web.Routing
ContentFinderCollection contentFinders,
IContentLastChanceFinder contentLastChanceFinder,
IVariationContextAccessor variationContextAccessor,
ServiceContext services,
IProfilingLogger proflog,
IUmbracoSettingsSection umbracoSettingsSection,
IHttpContextAccessor httpContextAccessor,
IPublishedUrlProvider publishedUrlProvider)
IPublishedUrlProvider publishedUrlProvider,
IRequestAccessor requestAccessor,
IPublishedValueFallback publishedValueFallback,
IPublicAccessChecker publicAccessChecker,
IFileService fileService,
IContentTypeService contentTypeService,
IPublicAccessService publicAccessService)
{
_webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection));
_contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders));
_contentLastChanceFinder = contentLastChanceFinder ?? throw new ArgumentNullException(nameof(contentLastChanceFinder));
_services = services ?? throw new ArgumentNullException(nameof(services));
_profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog));
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
_logger = proflog;
_umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
_httpContextAccessor = httpContextAccessor;
_publishedUrlProvider = publishedUrlProvider;
_requestAccessor = requestAccessor;
_publishedValueFallback = publishedValueFallback;
_publicAccessChecker = publicAccessChecker;
_fileService = fileService;
_contentTypeService = contentTypeService;
_publicAccessService = publicAccessService;
}
/// <inheritdoc />
@@ -358,7 +369,7 @@ namespace Umbraco.Web.Routing
/// <inheritdoc />
public ITemplate GetTemplate(string alias)
{
return _services.FileService.GetTemplate(alias);
return _fileService.GetTemplate(alias);
}
/// <summary>
@@ -498,7 +509,7 @@ namespace Umbraco.Web.Routing
var redirect = false;
var valid = false;
IPublishedContent internalRedirectNode = null;
var internalRedirectId = request.PublishedContent.Value(Constants.Conventions.Content.InternalRedirectId, defaultValue: -1);
var internalRedirectId = request.PublishedContent.Value(_publishedValueFallback, Constants.Conventions.Content.InternalRedirectId, defaultValue: -1);
if (internalRedirectId > 0)
{
@@ -508,7 +519,7 @@ namespace Umbraco.Web.Routing
}
else
{
var udiInternalRedirectId = request.PublishedContent.Value<GuidUdi>(Constants.Conventions.Content.InternalRedirectId);
var udiInternalRedirectId = request.PublishedContent.Value<GuidUdi>(_publishedValueFallback, Constants.Conventions.Content.InternalRedirectId);
if (udiInternalRedirectId != null)
{
// try and get the redirect node from a UDI Guid
@@ -555,58 +566,34 @@ namespace Umbraco.Web.Routing
var path = request.PublishedContent.Path;
var publicAccessAttempt = _services.PublicAccessService.IsProtected(path);
var publicAccessAttempt = _publicAccessService.IsProtected(path);
if (publicAccessAttempt)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Page is protected, check for access");
var membershipHelper = Current.Factory.GetInstance<MembershipHelper>();
if (membershipHelper.IsLoggedIn() == false)
var status = _publicAccessChecker.HasMemberAccessToContent(request.PublishedContent.Id);
switch (status)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Not logged in, redirect to login page");
var loginPageId = publicAccessAttempt.Result.LoginNodeId;
if (loginPageId != request.PublishedContent.Id)
request.PublishedContent = request.UmbracoContext.PublishedSnapshot.Content.GetById(loginPageId);
}
else if (_services.PublicAccessService.HasAccess(request.PublishedContent.Id, _services.ContentService, membershipHelper.CurrentUserName, membershipHelper.GetCurrentUserRoles()) == false)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Current member has not access, redirect to error page");
var errorPageId = publicAccessAttempt.Result.NoAccessNodeId;
if (errorPageId != request.PublishedContent.Id)
request.PublishedContent = request.UmbracoContext.PublishedSnapshot.Content.GetById(errorPageId);
}
else
{
// grab the current member
var member = membershipHelper.GetCurrentMember();
// if the member has the "approved" and/or "locked out" properties, make sure they're correctly set before allowing access
var memberIsActive = true;
if (member != null)
{
if (member.HasProperty(Constants.Conventions.Member.IsApproved) == false)
memberIsActive = member.Value<bool>(Constants.Conventions.Member.IsApproved);
if (member.HasProperty(Constants.Conventions.Member.IsLockedOut) == false)
memberIsActive = member.Value<bool>(Constants.Conventions.Member.IsLockedOut) == false;
}
if (memberIsActive == false)
{
_logger.Debug<PublishedRouter>(
"Current member is either unapproved or locked out, redirect to error page");
var errorPageId = publicAccessAttempt.Result.NoAccessNodeId;
if (errorPageId != request.PublishedContent.Id)
request.PublishedContent =
request.UmbracoContext.PublishedSnapshot.Content.GetById(errorPageId);
}
else
{
case PublicAccessStatus.NotLoggedIn:
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Not logged in, redirect to login page");
SetPublishedContentAsOtherPage(request, publicAccessAttempt.Result.LoginNodeId);
break;
case PublicAccessStatus.AccessDenied:
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Current member has not access, redirect to error page");
SetPublishedContentAsOtherPage(request, publicAccessAttempt.Result.NoAccessNodeId);
break;
case PublicAccessStatus.LockedOut:
_logger.Debug<PublishedRouter>("Current member is locked out, redirect to error page");
SetPublishedContentAsOtherPage(request, publicAccessAttempt.Result.NoAccessNodeId);
break;
case PublicAccessStatus.NotApproved:
_logger.Debug<PublishedRouter>("Current member is unapproved, redirect to error page");
SetPublishedContentAsOtherPage(request, publicAccessAttempt.Result.NoAccessNodeId);
break;
case PublicAccessStatus.AccessAccepted:
_logger.Debug<PublishedRouter>("Current member has access");
}
break;
}
}
else
@@ -615,6 +602,12 @@ namespace Umbraco.Web.Routing
}
}
private static void SetPublishedContentAsOtherPage(IPublishedRequest request, int errorPageId)
{
if (errorPageId != request.PublishedContent.Id)
request.PublishedContent = request.UmbracoContext.PublishedSnapshot.Content.GetById(errorPageId);
}
/// <summary>
/// Finds a template for the current node, if any.
/// </summary>
@@ -637,7 +630,7 @@ namespace Umbraco.Web.Routing
var useAltTemplate = request.IsInitialPublishedContent
|| (_webRoutingSection.InternalRedirectPreservesTemplate && request.IsInternalRedirectPublishedContent);
var altTemplate = useAltTemplate
? _httpContextAccessor.GetRequiredHttpContext().Request[Constants.Conventions.Url.AltTemplate]
? _requestAccessor.GetRequestValue(Constants.Conventions.Url.AltTemplate)
: null;
if (string.IsNullOrWhiteSpace(altTemplate))
@@ -674,10 +667,15 @@ namespace Umbraco.Web.Routing
_logger.Debug<PublishedRouter>("FindTemplate: Look for alternative template alias={AltTemplate}", altTemplate);
// IsAllowedTemplate deals both with DisableAlternativeTemplates and ValidateAlternativeTemplates settings
if (request.PublishedContent.IsAllowedTemplate(altTemplate))
if (request.PublishedContent.IsAllowedTemplate(
_fileService,
_contentTypeService,
_umbracoSettingsSection.WebRouting.DisableAlternativeTemplates,
_umbracoSettingsSection.WebRouting.ValidateAlternativeTemplates,
altTemplate))
{
// allowed, use
var template = _services.FileService.GetTemplate(altTemplate);
var template = _fileService.GetTemplate(altTemplate);
if (template != null)
{
@@ -731,7 +729,7 @@ namespace Umbraco.Web.Routing
if (templateId == null)
throw new InvalidOperationException("The template is not set, the page cannot render.");
var template = _services.FileService.GetTemplate(templateId.Value);
var template = _fileService.GetTemplate(templateId.Value);
if (template == null)
throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render.");
_logger.Debug<PublishedRouter>("GetTemplateModel: Got template id={TemplateId} alias={TemplateAlias}", template.Id, template.Alias);
@@ -750,7 +748,7 @@ namespace Umbraco.Web.Routing
if (request.PublishedContent.HasProperty(Constants.Conventions.Content.Redirect) == false)
return;
var redirectId = request.PublishedContent.Value(Constants.Conventions.Content.Redirect, defaultValue: -1);
var redirectId = request.PublishedContent.Value(_publishedValueFallback, Constants.Conventions.Content.Redirect, defaultValue: -1);
var redirectUrl = "#";
if (redirectId > 0)
{
@@ -759,7 +757,7 @@ namespace Umbraco.Web.Routing
else
{
// might be a UDI instead of an int Id
var redirectUdi = request.PublishedContent.Value<GuidUdi>(Constants.Conventions.Content.Redirect);
var redirectUdi = request.PublishedContent.Value<GuidUdi>(_publishedValueFallback, Constants.Conventions.Content.Redirect);
if (redirectUdi != null)
redirectUrl = _publishedUrlProvider.GetUrl(redirectUdi.Guid);
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Security
{
public interface IMemberUserKeyProvider
{
object GetMemberProviderUserKey();
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Web.Security
{
public interface IPublicAccessChecker
{
PublicAccessStatus HasMemberAccessToContent(int publishedContentId);
}
}
@@ -0,0 +1,11 @@
namespace Umbraco.Web.Security
{
public enum PublicAccessStatus
{
NotLoggedIn,
AccessDenied,
NotApproved,
LockedOut,
AccessAccepted
}
}
@@ -51,7 +51,10 @@ namespace Umbraco.Core.Services
IEnumerable<TItem> GetComposedOf(int id); // composition axis
IEnumerable<TItem> GetChildren(int id);
IEnumerable<TItem> GetChildren(Guid id);
bool HasChildren(int id);
bool HasChildren(Guid id);
void Save(TItem item, int userId = Constants.Security.SuperUserId);
void Save(IEnumerable<TItem> items, int userId = Constants.Security.SuperUserId);
@@ -0,0 +1,8 @@
namespace Umbraco.Core.Session
{
public interface ISessionManager
{
object GetSessionValue(string sessionName);
void SetSessionValue(string sessionName, object value);
}
}
@@ -3,8 +3,10 @@ namespace Umbraco.Core.Sync
/// <summary>
/// An <see cref="IServerMessenger"/> implementation that works by storing messages in the database.
/// </summary>
public interface IBatchedDatabaseServerMessenger : IServerMessenger
public interface IBatchedDatabaseServerMessenger : IDatabaseServerMessenger
{
void FlushBatch();
DatabaseServerMessengerOptions Options { get; }
void Startup();
}
}
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Sync
{
public interface IDatabaseServerMessenger: IServerMessenger
{
void Sync();
}
}
@@ -0,0 +1,19 @@
using System;
using Umbraco.Web;
namespace Umbraco.Core
{
public static class UmbracoContextAccessorExtensions
{
public static IUmbracoContext GetRequiredUmbracoContext(this IUmbracoContextAccessor umbracoContextAccessor)
{
if (umbracoContextAccessor == null) throw new ArgumentNullException(nameof(umbracoContextAccessor));
var umbracoContext = umbracoContextAccessor.UmbracoContext;
if(umbracoContext is null) throw new InvalidOperationException("UmbracoContext is null");
return umbracoContext;
}
}
}
+1 -1
View File
@@ -336,7 +336,7 @@ namespace Umbraco.Core.Xml
var child = parent.SelectSingleNode(name);
if (child != null)
{
child.InnerXml = "<![CDATA[" + value + "]]>"; ;
child.InnerXml = "<![CDATA[" + value + "]]>";
return child;
}
return AddCDataNode(xd, name, value);
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using Examine;
using Examine.LuceneEngine.Directories;
using Lucene.Net.Store;
using Umbraco.Core.Configuration;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
@@ -19,11 +19,13 @@ namespace Umbraco.Examine
{
private readonly ITypeFinder _typeFinder;
private readonly IIOHelper _ioHelper;
private readonly IIndexCreatorSettings _settings;
protected LuceneIndexCreator(ITypeFinder typeFinder, IIOHelper ioHelper)
protected LuceneIndexCreator(ITypeFinder typeFinder, IIOHelper ioHelper, IIndexCreatorSettings settings)
{
_typeFinder = typeFinder;
_ioHelper = ioHelper;
_settings = settings;
}
public abstract IEnumerable<IIndex> Create();
@@ -43,7 +45,8 @@ namespace Umbraco.Examine
System.IO.Directory.CreateDirectory(dirInfo.FullName);
//check if there's a configured directory factory, if so create it and use that to create the lucene dir
var configuredDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
var configuredDirectoryFactory = _settings.LuceneDirectoryFactory;
if (!configuredDirectoryFactory.IsNullOrWhiteSpace())
{
//this should be a fully qualified type
@@ -4,6 +4,7 @@ using Umbraco.Core.Services;
using Lucene.Net.Analysis.Standard;
using Examine.LuceneEngine;
using Examine;
using Umbraco.Core.Configuration;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
@@ -25,7 +26,8 @@ namespace Umbraco.Examine
IMemberService memberService,
IUmbracoIndexConfig umbracoIndexConfig,
IIOHelper ioHelper,
IRuntimeState runtimeState) : base(typeFinder, ioHelper)
IRuntimeState runtimeState,
IIndexCreatorSettings settings) : base(typeFinder, ioHelper, settings)
{
ProfilingLogger = profilingLogger ?? throw new System.ArgumentNullException(nameof(profilingLogger));
LanguageService = languageService ?? throw new System.ArgumentNullException(nameof(languageService));
@@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Sync;
using Umbraco.Web.Routing;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Scoping;
using Umbraco.Web.Composing;
using System.ComponentModel;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Request;
namespace Umbraco.Web
{
@@ -29,19 +25,30 @@ namespace Umbraco.Web
{
private readonly IUmbracoDatabaseFactory _databaseFactory;
private readonly IRequestCache _requestCache;
private readonly IRequestAccessor _requestAccessor;
public BatchedDatabaseServerMessenger(
IRuntimeState runtime, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers, IRequestCache requestCache)
IRuntimeState runtime,
IUmbracoDatabaseFactory databaseFactory,
IScopeProvider scopeProvider,
ISqlContext sqlContext,
IProfilingLogger proflog,
DatabaseServerMessengerOptions options,
IHostingEnvironment hostingEnvironment,
CacheRefresherCollection cacheRefreshers,
IRequestCache requestCache,
IRequestAccessor requestAccessor)
: base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers)
{
_databaseFactory = databaseFactory;
_requestCache = requestCache;
_requestAccessor = requestAccessor;
}
// invoked by DatabaseServerRegistrarAndMessengerComponent
internal void Startup()
public void Startup()
{
UmbracoModule.EndRequest += UmbracoModule_EndRequest;
_requestAccessor.EndRequest += UmbracoModule_EndRequest;
if (_databaseFactory.CanConnect == false)
{
@@ -104,7 +111,7 @@ namespace Umbraco.Web
protected ICollection<RefreshInstructionEnvelope> GetBatch(bool create)
{
var key = typeof (BatchedDatabaseServerMessenger).Name;
var key = nameof(BatchedDatabaseServerMessenger);
if (!_requestCache.IsAvailable) return null;
@@ -4,6 +4,7 @@ using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.Request;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
using Umbraco.Core.Sync;
@@ -82,7 +83,7 @@ namespace Umbraco.Web.Compose
{
private object _locker = new object();
private readonly DatabaseServerRegistrar _registrar;
private readonly BatchedDatabaseServerMessenger _messenger;
private readonly IBatchedDatabaseServerMessenger _messenger;
private readonly IRuntimeState _runtime;
private readonly ILogger _logger;
private readonly IServerRegistrationService _registrationService;
@@ -91,13 +92,23 @@ namespace Umbraco.Web.Compose
private bool _started;
private IBackgroundTask[] _tasks;
private IndexRebuilder _indexRebuilder;
private readonly IRequestAccessor _requestAccessor;
public DatabaseServerRegistrarAndMessengerComponent(IRuntimeState runtime, IServerRegistrar serverRegistrar, IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder)
public DatabaseServerRegistrarAndMessengerComponent(
IRuntimeState runtime,
IServerRegistrar serverRegistrar,
IServerMessenger serverMessenger,
IServerRegistrationService registrationService,
ILogger logger,
IHostingEnvironment hostingEnvironment,
IndexRebuilder indexRebuilder,
IRequestAccessor requestAccessor)
{
_runtime = runtime;
_logger = logger;
_registrationService = registrationService;
_indexRebuilder = indexRebuilder;
_requestAccessor = requestAccessor;
// create task runner for DatabaseServerRegistrar
_registrar = serverRegistrar as DatabaseServerRegistrar;
@@ -108,7 +119,7 @@ namespace Umbraco.Web.Compose
}
// create task runner for BatchedDatabaseServerMessenger
_messenger = serverMessenger as BatchedDatabaseServerMessenger;
_messenger = serverMessenger as IBatchedDatabaseServerMessenger;
if (_messenger != null)
{
_processTaskRunner = new BackgroundTaskRunner<IBackgroundTask>("ServerInstProcess",
@@ -120,7 +131,7 @@ namespace Umbraco.Web.Compose
{
//We will start the whole process when a successful request is made
if (_registrar != null || _messenger != null)
UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce;
_requestAccessor.RouteAttempt += RegisterBackgroundTasksOnce;
// must come last, as it references some _variables
_messenger?.Startup();
@@ -137,7 +148,7 @@ namespace Umbraco.Web.Compose
/// <remarks>
/// We require this because:
/// - ApplicationContext.UmbracoApplicationUrl is initialized by UmbracoModule in BeginRequest
/// - RegisterServer is called on UmbracoModule.RouteAttempt which is triggered in ProcessRequest
/// - RegisterServer is called on _requestAccessor.RouteAttempt which is triggered in ProcessRequest
/// we are safe, UmbracoApplicationUrl has been initialized
/// </remarks>
private void RegisterBackgroundTasksOnce(object sender, RoutableAttemptEventArgs e)
@@ -146,7 +157,7 @@ namespace Umbraco.Web.Compose
{
case EnsureRoutableOutcome.IsRoutable:
case EnsureRoutableOutcome.NotDocumentRequest:
UmbracoModule.RouteAttempt -= RegisterBackgroundTasksOnce;
_requestAccessor.RouteAttempt -= RegisterBackgroundTasksOnce;
RegisterBackgroundTasks();
break;
}
@@ -196,11 +207,11 @@ namespace Umbraco.Web.Compose
private class InstructionProcessTask : RecurringTaskBase
{
private readonly DatabaseServerMessenger _messenger;
private readonly IDatabaseServerMessenger _messenger;
private readonly ILogger _logger;
public InstructionProcessTask(IBackgroundTaskRunner<RecurringTaskBase> runner, int delayMilliseconds, int periodMilliseconds,
DatabaseServerMessenger messenger, ILogger logger)
IDatabaseServerMessenger messenger, ILogger logger)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_messenger = messenger;
@@ -4,6 +4,7 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
using Umbraco.Net;
namespace Umbraco.Core.Compose
{
@@ -12,18 +13,18 @@ namespace Umbraco.Core.Compose
private readonly IRuntimeState _runtimeState;
private readonly ILogger _logger;
private readonly IIOHelper _ioHelper;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
// if configured and in debug mode, a ManifestWatcher watches App_Plugins folders for
// package.manifest chances and restarts the application on any change
private ManifestWatcher _mw;
public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment)
public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_runtimeState = runtimeState;
_logger = logger;
_ioHelper = ioHelper;
_hostingEnvironment = hostingEnvironment;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
}
public void Initialize()
@@ -36,7 +37,7 @@ namespace Umbraco.Core.Compose
var appPlugins = _ioHelper.MapPath("~/App_Plugins/");
if (Directory.Exists(appPlugins) == false) return;
_mw = new ManifestWatcher(_logger, _hostingEnvironment);
_mw = new ManifestWatcher(_logger, _umbracoApplicationLifetime);
_mw.Start(Directory.GetDirectories(appPlugins));
}
@@ -1,4 +1,6 @@
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Configuration;
using Umbraco.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
namespace Umbraco.Core.Composing.CompositionExtensions
{
@@ -13,12 +13,18 @@ namespace Umbraco.Web
/// </summary>
public interface IPublishedContentQuery
{
IPublishedContent Content(int id);
IPublishedContent Content(Guid id);
IPublishedContent Content(Udi id);
IPublishedContent Content(object id);
IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars);
IEnumerable<IPublishedContent> Content(IEnumerable<int> ids);
IEnumerable<IPublishedContent> Content(IEnumerable<Guid> ids);
IEnumerable<IPublishedContent> Content(IEnumerable<object> ids);
IEnumerable<IPublishedContent> ContentAtXPath(string xpath, params XPathVariable[] vars);
IEnumerable<IPublishedContent> ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars);
IEnumerable<IPublishedContent> ContentAtRoot();
@@ -26,7 +32,10 @@ namespace Umbraco.Web
IPublishedContent Media(int id);
IPublishedContent Media(Guid id);
IPublishedContent Media(Udi id);
IPublishedContent Media(object id);
IEnumerable<IPublishedContent> Media(IEnumerable<int> ids);
IEnumerable<IPublishedContent> Media(IEnumerable<object> ids);
IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids);
IEnumerable<IPublishedContent> MediaAtRoot();
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Cookie;
@@ -11,9 +10,9 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Serialization;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install
@@ -22,25 +21,28 @@ namespace Umbraco.Web.Install
{
private static HttpClient _httpClient;
private readonly DatabaseBuilder _databaseBuilder;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger _logger;
private readonly IGlobalSettings _globalSettings;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IConnectionStrings _connectionStrings;
private readonly IInstallationService _installationService;
private readonly ICookieManager _cookieManager;
private readonly IUserAgentProvider _userAgentProvider;
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
private readonly IJsonSerializer _jsonSerializer;
private InstallationType? _installationType;
public InstallHelper(IHttpContextAccessor httpContextAccessor,
DatabaseBuilder databaseBuilder,
public InstallHelper(DatabaseBuilder databaseBuilder,
ILogger logger,
IGlobalSettings globalSettings,
IUmbracoVersion umbracoVersion,
IConnectionStrings connectionStrings,
IInstallationService installationService,
ICookieManager cookieManager)
ICookieManager cookieManager,
IUserAgentProvider userAgentProvider,
IUmbracoDatabaseFactory umbracoDatabaseFactory,
IJsonSerializer jsonSerializer)
{
_httpContextAccessor = httpContextAccessor;
_logger = logger;
_globalSettings = globalSettings;
_umbracoVersion = umbracoVersion;
@@ -48,6 +50,9 @@ namespace Umbraco.Web.Install
_connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings));
_installationService = installationService;
_cookieManager = cookieManager;
_userAgentProvider = userAgentProvider;
_umbracoDatabaseFactory = umbracoDatabaseFactory;
_jsonSerializer = jsonSerializer;
}
public InstallationType GetInstallationType()
@@ -57,11 +62,9 @@ namespace Umbraco.Web.Install
public async Task InstallStatus(bool isCompleted, string errorMsg)
{
var httpContext = _httpContextAccessor.GetRequiredHttpContext();
try
{
var userAgent = httpContext.Request.UserAgent;
var userAgent = _userAgentProvider.GetUserAgent();
// Check for current install Id
var installId = Guid.NewGuid();
@@ -88,7 +91,7 @@ namespace Umbraco.Web.Install
{
// we don't have DatabaseProvider anymore... doing it differently
//dbProvider = ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString();
dbProvider = GetDbProviderString(Current.SqlContext);
dbProvider = _umbracoDatabaseFactory.SqlContext.SqlSyntax.DbProvider;
}
var installLog = new InstallLog(installId: installId, isUpgrade: IsBrandNewInstall == false,
@@ -105,23 +108,6 @@ namespace Umbraco.Web.Install
}
}
internal static string GetDbProviderString(ISqlContext sqlContext)
{
var dbProvider = string.Empty;
// we don't have DatabaseProvider anymore...
//dbProvider = ApplicationContext.Current.DatabaseContext.DatabaseProvider.ToString();
//
// doing it differently
var syntax = sqlContext.SqlSyntax;
if (syntax is SqlCeSyntaxProvider)
dbProvider = "SqlServerCE";
else if (syntax is SqlServerSyntaxProvider)
dbProvider = (syntax as SqlServerSyntaxProvider).ServerVersion.IsAzure ? "SqlAzure" : "SqlServer";
return dbProvider;
}
/// <summary>
/// Checks if this is a brand new install meaning that there is no configured version and there is no configured database connection
/// </summary>
@@ -162,7 +148,10 @@ namespace Umbraco.Web.Install
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
var response = _httpClient.SendAsync(request).Result;
packages = response.Content.ReadAsAsync<IEnumerable<Package>>().Result.ToList();
var json = response.Content.ReadAsStringAsync().Result;
packages = _jsonSerializer.Deserialize<IEnumerable<Package>>(json).ToList();
}
}
catch (AggregateException ex)
@@ -1,7 +1,7 @@
using System.Linq;
using System.Threading.Tasks;
using System.Web.Configuration;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Security;
using Umbraco.Web.Install.Models;
@@ -12,13 +12,15 @@ namespace Umbraco.Web.Install.InstallSteps
"ConfigureMachineKey", "machinekey", 2,
"Updating some security settings...",
PerformsAppRestart = true)]
internal class ConfigureMachineKey : InstallSetupStep<bool?>
public class ConfigureMachineKey : InstallSetupStep<bool?>
{
private readonly IIOHelper _ioHelper;
private readonly IMachineKeyConfig _machineKeyConfig;
public ConfigureMachineKey(IIOHelper ioHelper)
public ConfigureMachineKey(IIOHelper ioHelper, IMachineKeyConfig machineKeyConfig)
{
_ioHelper = ioHelper;
_machineKeyConfig = machineKeyConfig;
}
public override string View => HasMachineKey() == false ? base.View : "";
@@ -27,10 +29,9 @@ namespace Umbraco.Web.Install.InstallSteps
/// Don't display the view or execute if a machine key already exists
/// </summary>
/// <returns></returns>
private static bool HasMachineKey()
private bool HasMachineKey()
{
var section = (MachineKeySection) WebConfigurationManager.GetSection("system.web/machineKey");
return section.ElementInformation.Source != null;
return _machineKeyConfig.HasMachineKey;
}
/// <summary>
@@ -1,44 +1,31 @@
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Services;
using Umbraco.Web.Cache;
using Umbraco.Web.Composing;
using Umbraco.Web.Install.Models;
using Umbraco.Web.Security;
namespace Umbraco.Web.Install.InstallSteps
{
[InstallSetupStep(InstallationType.NewInstall | InstallationType.Upgrade,
"UmbracoVersion", 50, "Installation is complete!, get ready to be redirected to your new CMS.",
"UmbracoVersion", 50, "Installation is complete! Get ready to be redirected to your new CMS.",
PerformsAppRestart = true)]
internal class SetUmbracoVersionStep : InstallSetupStep<object>
public class SetUmbracoVersionStep : InstallSetupStep<object>
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly InstallHelper _installHelper;
private readonly IGlobalSettings _globalSettings;
private readonly IUserService _userService;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IIOHelper _ioHelper;
public SetUmbracoVersionStep(IHttpContextAccessor httpContextAccessor, InstallHelper installHelper, IGlobalSettings globalSettings, IUserService userService, IUmbracoVersion umbracoVersion, IIOHelper ioHelper)
public SetUmbracoVersionStep(IUmbracoContextAccessor umbracoContextAccessor, InstallHelper installHelper, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion)
{
_httpContextAccessor = httpContextAccessor;
_umbracoContextAccessor = umbracoContextAccessor;
_installHelper = installHelper;
_globalSettings = globalSettings;
_userService = userService;
_umbracoVersion = umbracoVersion;
_ioHelper = ioHelper;
}
public override Task<InstallSetupResult> ExecuteAsync(object model)
{
var security = new WebSecurity(_httpContextAccessor, _userService, _globalSettings, _ioHelper);
var security = _umbracoContextAccessor.GetRequiredUmbracoContext().Security;
if (security.IsAuthenticated() == false && _globalSettings.ConfigurationStatus.IsNullOrWhiteSpace())
{
security.PerformLogin(-1);
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Services;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Packaging;
using Umbraco.Web.Composing;
using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -20,14 +18,16 @@ namespace Umbraco.Web.Install.InstallSteps
private readonly InstallHelper _installHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly IContentService _contentService;
private readonly IPackagingService _packageService;
public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoVersion umbracoVersion)
public StarterKitDownloadStep(IContentService contentService, IPackagingService packageService, InstallHelper installHelper, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoVersion umbracoVersion, IUmbracoApplicationLifetime umbracoApplicationLifetime)
{
_installHelper = installHelper;
_umbracoContextAccessor = umbracoContextAccessor;
_umbracoVersion = umbracoVersion;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
_contentService = contentService;
_packageService = packageService;
}
@@ -54,7 +54,7 @@ namespace Umbraco.Web.Install.InstallSteps
var (packageFile, packageId) = await DownloadPackageFilesAsync(starterKitId.Value);
UmbracoApplication.Restart();
_umbracoApplicationLifetime.Restart();
return new InstallSetupResult(new Dictionary<string, object>
{
@@ -2,9 +2,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Net;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -14,13 +13,13 @@ namespace Umbraco.Web.Install.InstallSteps
PerformsAppRestart = true)]
internal class StarterKitInstallStep : InstallSetupStep<object>
{
private readonly IHttpContextAccessor _httContextAccessor;
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IPackagingService _packagingService;
public StarterKitInstallStep(IHttpContextAccessor httContextAccessor, IUmbracoContextAccessor umbracoContextAccessor, IPackagingService packagingService)
public StarterKitInstallStep(IUmbracoApplicationLifetime umbracoApplicationLifetime, IUmbracoContextAccessor umbracoContextAccessor, IPackagingService packagingService)
{
_httContextAccessor = httContextAccessor;
_umbracoApplicationLifetime = umbracoApplicationLifetime;
_umbracoContextAccessor = umbracoContextAccessor;
_packagingService = packagingService;
}
@@ -34,7 +33,9 @@ namespace Umbraco.Web.Install.InstallSteps
InstallBusinessLogic(packageId);
UmbracoApplication.Restart(_httContextAccessor.GetRequiredHttpContext());
_umbracoApplicationLifetime.Restart();
return Task.FromResult<InstallSetupResult>(null);
}
@@ -12,7 +12,7 @@ namespace Umbraco.Web.Media.Exif
public ExifBitConverter(ByteOrder from, ByteOrder to)
: base(from, to)
{
;
}
#endregion
@@ -28,7 +28,7 @@ namespace Umbraco.Web.Media.Exif
public ExifEnumProperty(ExifTag tag, T value)
: this(tag, value, false)
{
;
}
public override ExifInterOperability Interoperability
@@ -210,13 +210,13 @@ namespace Umbraco.Web.Media.Exif
public ExifPointSubjectArea(ExifTag tag, ushort[] value)
: base(tag, value)
{
;
}
public ExifPointSubjectArea(ExifTag tag, ushort x, ushort y)
: base(tag, new ushort[] { x, y })
: base(tag, new ushort[] {x, y})
{
;
}
}
@@ -239,13 +239,13 @@ namespace Umbraco.Web.Media.Exif
public ExifCircularSubjectArea(ExifTag tag, ushort[] value)
: base(tag, value)
{
;
}
public ExifCircularSubjectArea(ExifTag tag, ushort x, ushort y, ushort d)
: base(tag, new ushort[] { x, y, d })
{
;
}
}
@@ -269,13 +269,13 @@ namespace Umbraco.Web.Media.Exif
public ExifRectangularSubjectArea(ExifTag tag, ushort[] value)
: base(tag, value)
{
;
}
public ExifRectangularSubjectArea(ExifTag tag, ushort x, ushort y, ushort w, ushort h)
: base(tag, new ushort[] { x, y, w, h })
{
;
}
}
@@ -303,13 +303,13 @@ namespace Umbraco.Web.Media.Exif
public GPSLatitudeLongitude(ExifTag tag, MathEx.UFraction32[] value)
: base(tag, value)
{
;
}
public GPSLatitudeLongitude(ExifTag tag, float d, float m, float s)
: base(tag, new MathEx.UFraction32[] { new MathEx.UFraction32(d), new MathEx.UFraction32(m), new MathEx.UFraction32(s) })
{
;
}
}
@@ -331,13 +331,13 @@ namespace Umbraco.Web.Media.Exif
public GPSTimeStamp(ExifTag tag, MathEx.UFraction32[] value)
: base(tag, value)
{
;
}
public GPSTimeStamp(ExifTag tag, float h, float m, float s)
: base(tag, new MathEx.UFraction32[] { new MathEx.UFraction32(h), new MathEx.UFraction32(m), new MathEx.UFraction32(s) })
{
;
}
}
@@ -19,7 +19,7 @@ namespace Umbraco.Web.Media.Exif
public JFIFVersion(ExifTag tag, ushort value)
: base(tag, value)
{
;
}
public override string ToString()
@@ -45,7 +45,7 @@
public JPEGSection(JPEGMarker marker)
: this(marker, new byte[0], new byte[0])
{
;
}
#endregion
+12 -12
View File
@@ -403,37 +403,37 @@ namespace Umbraco.Web.Media.Exif
public Fraction32(int numerator, int denominator)
: this(numerator, denominator, 0)
{
;
}
public Fraction32(int numerator)
: this(numerator, (int)1)
{
;
}
public Fraction32(Fraction32 f)
: this(f.Numerator, f.Denominator, f.Error)
{
;
}
public Fraction32(float value)
: this((double)value)
{
;
}
public Fraction32(double value)
: this(FromDouble(value))
{
;
}
public Fraction32(string s)
: this(FromString(s))
{
;
}
#endregion
@@ -1033,37 +1033,37 @@ namespace Umbraco.Web.Media.Exif
public UFraction32(uint numerator, uint denominator)
: this(numerator, denominator, 0)
{
;
}
public UFraction32(uint numerator)
: this(numerator, (uint)1)
{
;
}
public UFraction32(UFraction32 f)
: this(f.Numerator, f.Denominator, f.Error)
{
;
}
public UFraction32(float value)
: this((double)value)
{
;
}
public UFraction32(double value)
: this(FromDouble(value))
{
;
}
public UFraction32(string s)
: this(FromString(s))
{
;
}
#endregion
@@ -2,7 +2,6 @@
using Umbraco.Core.Cookie;
using Umbraco.Core.Migrations;
namespace Umbraco.Web.Migrations.PostMigrations
{
/// <summary>
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
if (string.IsNullOrEmpty(dataType.Configuration))
{
config.Format = "YYYY-MM-DD";
};
}
}
catch (Exception ex)
{
@@ -158,7 +158,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IMacro entity)
{
entity.UpdatingEntity();
;
var dto = MacroFactory.BuildDto(entity);
Database.Update(dto);
@@ -219,7 +219,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
//Save updated entity to db
template.UpdateDate = DateTime.Now;
;
var dto = TemplateFactory.BuildDto(template, NodeObjectTypeId, templateDto.PrimaryKey);
Database.Update(dto.NodeDto);
@@ -77,12 +77,13 @@ namespace Umbraco.Core.Persistence.SqlSyntax
string ConvertIntegerToOrderableString { get; }
string ConvertDateToOrderableString { get; }
string ConvertDecimalToOrderableString { get; }
/// <summary>
/// Returns the default isolation level for the database
/// </summary>
IsolationLevel DefaultIsolationLevel { get; }
string DbProvider { get; }
IEnumerable<string> GetTablesInSchema(IDatabase db);
IEnumerable<ColumnInfo> GetColumnsInSchema(IDatabase db);
@@ -175,6 +175,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override string DbProvider => ServerVersion.IsAzure ? "SqlAzure" : "SqlServer";
public override IEnumerable<string> GetTablesInSchema(IDatabase db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
@@ -202,6 +202,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
}
public abstract IsolationLevel DefaultIsolationLevel { get; }
public abstract string DbProvider { get; }
public virtual IEnumerable<string> GetTablesInSchema(IDatabase db)
{
@@ -48,7 +48,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
value = new ImageCropperValue { Src = sourceString };
}
value.ApplyConfiguration(propertyType.DataType.ConfigurationAs<ImageCropperConfiguration>());
value?.ApplyConfiguration(propertyType.DataType.ConfigurationAs<ImageCropperConfiguration>());
return value;
}
@@ -14,35 +14,85 @@ using Umbraco.Web.PublishedCache;
namespace Umbraco.Web
{
/// <summary>
/// A class used to query for published content, media items
/// A class used to query for published content, media items
/// </summary>
public class PublishedContentQuery : IPublishedContentQuery
{
private readonly IExamineManager _examineManager;
private readonly IPublishedSnapshot _publishedSnapshot;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IExamineManager _examineManager;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedContentQuery"/> class.
/// Initializes a new instance of the <see cref="PublishedContentQuery" /> class.
/// </summary>
public PublishedContentQuery(IPublishedSnapshot publishedSnapshot, IVariationContextAccessor variationContextAccessor, IExamineManager examineManager)
public PublishedContentQuery(IPublishedSnapshot publishedSnapshot,
IVariationContextAccessor variationContextAccessor, IExamineManager examineManager)
{
_publishedSnapshot = publishedSnapshot ?? throw new ArgumentNullException(nameof(publishedSnapshot));
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
_variationContextAccessor = variationContextAccessor ??
throw new ArgumentNullException(nameof(variationContextAccessor));
_examineManager = examineManager ?? throw new ArgumentNullException(nameof(examineManager));
}
#region Convert Helpers
private static bool ConvertIdObjectToInt(object id, out int intId)
{
switch (id)
{
case string s:
return int.TryParse(s, out intId);
case int i:
intId = i;
return true;
default:
intId = default;
return false;
}
}
private static bool ConvertIdObjectToGuid(object id, out Guid guidId)
{
switch (id)
{
case string s:
return Guid.TryParse(s, out guidId);
case Guid g:
guidId = g;
return true;
default:
guidId = default;
return false;
}
}
private static bool ConvertIdObjectToUdi(object id, out Udi guidId)
{
switch (id)
{
case string s:
return UdiParser.TryParse(s, out guidId);
case Udi u:
guidId = u;
return true;
default:
guidId = default;
return false;
}
}
#endregion
#region Content
public IPublishedContent Content(int id)
{
return ItemById(id, _publishedSnapshot.Content);
}
public IPublishedContent Content(int id) => ItemById(id, _publishedSnapshot.Content);
public IPublishedContent Content(Guid id)
{
return ItemById(id, _publishedSnapshot.Content);
}
public IPublishedContent Content(Guid id) => ItemById(id, _publishedSnapshot.Content);
public IPublishedContent Content(Udi id)
{
@@ -50,49 +100,45 @@ namespace Umbraco.Web
return ItemById(udi.Guid, _publishedSnapshot.Content);
}
public IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars)
public IPublishedContent Content(object id)
{
return ItemByXPath(xpath, vars, _publishedSnapshot.Content);
if (ConvertIdObjectToInt(id, out var intId))
return Content(intId);
if (ConvertIdObjectToGuid(id, out var guidId))
return Content(guidId);
if (ConvertIdObjectToUdi(id, out var udiId))
return Content(udiId);
return null;
}
public IEnumerable<IPublishedContent> Content(IEnumerable<int> ids)
{
return ItemsByIds(_publishedSnapshot.Content, ids);
}
public IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars) =>
ItemByXPath(xpath, vars, _publishedSnapshot.Content);
public IEnumerable<IPublishedContent> Content(IEnumerable<Guid> ids)
{
return ItemsByIds(_publishedSnapshot.Content, ids);
}
public IEnumerable<IPublishedContent> Content(IEnumerable<int> ids) =>
ItemsByIds(_publishedSnapshot.Content, ids);
public IEnumerable<IPublishedContent> ContentAtXPath(string xpath, params XPathVariable[] vars)
{
return ItemsByXPath(xpath, vars, _publishedSnapshot.Content);
}
public IEnumerable<IPublishedContent> Content(IEnumerable<Guid> ids) =>
ItemsByIds(_publishedSnapshot.Content, ids);
public IEnumerable<IPublishedContent> ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars)
public IEnumerable<IPublishedContent> Content(IEnumerable<object> ids)
{
return ItemsByXPath(xpath, vars, _publishedSnapshot.Content);
return ids.Select(Content).WhereNotNull();
}
public IEnumerable<IPublishedContent> ContentAtXPath(string xpath, params XPathVariable[] vars) =>
ItemsByXPath(xpath, vars, _publishedSnapshot.Content);
public IEnumerable<IPublishedContent> ContentAtRoot()
{
return ItemsAtRoot(_publishedSnapshot.Content);
}
public IEnumerable<IPublishedContent> ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars) =>
ItemsByXPath(xpath, vars, _publishedSnapshot.Content);
public IEnumerable<IPublishedContent> ContentAtRoot() => ItemsAtRoot(_publishedSnapshot.Content);
#endregion
#region Media
public IPublishedContent Media(int id)
{
return ItemById(id, _publishedSnapshot.Media);
}
public IPublishedContent Media(int id) => ItemById(id, _publishedSnapshot.Media);
public IPublishedContent Media(Guid id)
{
return ItemById(id, _publishedSnapshot.Media);
}
public IPublishedContent Media(Guid id) => ItemById(id, _publishedSnapshot.Media);
public IPublishedContent Media(Udi id)
{
@@ -100,21 +146,26 @@ namespace Umbraco.Web
return ItemById(udi.Guid, _publishedSnapshot.Media);
}
public IEnumerable<IPublishedContent> Media(IEnumerable<int> ids)
public IPublishedContent Media(object id)
{
return ItemsByIds(_publishedSnapshot.Media, ids);
if (ConvertIdObjectToInt(id, out var intId))
return Media(intId);
if (ConvertIdObjectToGuid(id, out var guidId))
return Media(guidId);
if (ConvertIdObjectToUdi(id, out var udiId))
return Media(udiId);
return null;
}
public IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids)
public IEnumerable<IPublishedContent> Media(IEnumerable<int> ids) => ItemsByIds(_publishedSnapshot.Media, ids);
public IEnumerable<IPublishedContent> Media(IEnumerable<object> ids)
{
return ItemsByIds(_publishedSnapshot.Media, ids);
return ids.Select(Media).WhereNotNull();
}
public IEnumerable<IPublishedContent> MediaAtRoot()
{
return ItemsAtRoot(_publishedSnapshot.Media);
}
public IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids) => ItemsByIds(_publishedSnapshot.Media, ids);
public IEnumerable<IPublishedContent> MediaAtRoot() => ItemsAtRoot(_publishedSnapshot.Media);
#endregion
@@ -155,44 +206,45 @@ namespace Umbraco.Web
return ids.Select(eachId => ItemById(eachId, cache)).WhereNotNull();
}
private static IEnumerable<IPublishedContent> ItemsByXPath(string xpath, XPathVariable[] vars, IPublishedCache cache)
private static IEnumerable<IPublishedContent> ItemsByXPath(string xpath, XPathVariable[] vars,
IPublishedCache cache)
{
var doc = cache.GetByXPath(xpath, vars);
return doc;
}
private static IEnumerable<IPublishedContent> ItemsByXPath(XPathExpression xpath, XPathVariable[] vars, IPublishedCache cache)
private static IEnumerable<IPublishedContent> ItemsByXPath(XPathExpression xpath, XPathVariable[] vars,
IPublishedCache cache)
{
var doc = cache.GetByXPath(xpath, vars);
return doc;
}
private static IEnumerable<IPublishedContent> ItemsAtRoot(IPublishedCache cache)
{
return cache.GetAtRoot();
}
private static IEnumerable<IPublishedContent> ItemsAtRoot(IPublishedCache cache) => cache.GetAtRoot();
#endregion
#region Search
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(string term, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
{
return Search(term, 0, 0, out _, culture, indexName);
}
public IEnumerable<PublishedSearchResult> Search(string term, string culture = "*",
string indexName = Constants.UmbracoIndexes.ExternalIndexName) =>
Search(term, 0, 0, out _, culture, indexName);
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords, string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
public IEnumerable<PublishedSearchResult> Search(string term, int skip, int take, out long totalRecords,
string culture = "*", string indexName = Constants.UmbracoIndexes.ExternalIndexName)
{
if (skip < 0)
{
throw new ArgumentOutOfRangeException(nameof(skip), skip, "The value must be greater than or equal to zero.");
throw new ArgumentOutOfRangeException(nameof(skip), skip,
"The value must be greater than or equal to zero.");
}
if (take < 0)
{
throw new ArgumentOutOfRangeException(nameof(take), take, "The value must be greater than or equal to zero.");
throw new ArgumentOutOfRangeException(nameof(take), take,
"The value must be greater than or equal to zero.");
}
if (string.IsNullOrEmpty(indexName))
@@ -202,7 +254,8 @@ namespace Umbraco.Web
if (!_examineManager.TryGetIndex(indexName, out var index) || !(index is IUmbracoIndex umbIndex))
{
throw new InvalidOperationException($"No index found by name {indexName} or is not of type {typeof(IUmbracoIndex)}");
throw new InvalidOperationException(
$"No index found by name {indexName} or is not of type {typeof(IUmbracoIndex)}");
}
var query = umbIndex.GetSearcher().CreateQuery(IndexTypes.Content);
@@ -216,13 +269,16 @@ namespace Umbraco.Web
else if (string.IsNullOrWhiteSpace(culture))
{
// Only search invariant
queryExecutor = query.Field(UmbracoExamineFieldNames.VariesByCultureFieldName, "n") // Must not vary by culture
queryExecutor = query
.Field(UmbracoExamineFieldNames.VariesByCultureFieldName, "n") // Must not vary by culture
.And().ManagedQuery(term);
}
else
{
// Only search the specified culture
var fields = umbIndex.GetCultureAndInvariantFields(culture).ToArray(); // Get all index fields suffixed with the culture name supplied
var fields =
umbIndex.GetCultureAndInvariantFields(culture)
.ToArray(); // Get all index fields suffixed with the culture name supplied
queryExecutor = query.ManagedQuery(term, fields);
}
@@ -232,26 +288,28 @@ namespace Umbraco.Web
totalRecords = results.TotalItemCount;
return new CultureContextualSearchResults(results.Skip(skip).ToPublishedSearchResults(_publishedSnapshot.Content), _variationContextAccessor, culture);
return new CultureContextualSearchResults(
results.Skip(skip).ToPublishedSearchResults(_publishedSnapshot.Content), _variationContextAccessor,
culture);
}
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(IQueryExecutor query)
{
return Search(query, 0, 0, out _);
}
public IEnumerable<PublishedSearchResult> Search(IQueryExecutor query) => Search(query, 0, 0, out _);
/// <inheritdoc />
public IEnumerable<PublishedSearchResult> Search(IQueryExecutor query, int skip, int take, out long totalRecords)
public IEnumerable<PublishedSearchResult> Search(IQueryExecutor query, int skip, int take,
out long totalRecords)
{
if (skip < 0)
{
throw new ArgumentOutOfRangeException(nameof(skip), skip, "The value must be greater than or equal to zero.");
throw new ArgumentOutOfRangeException(nameof(skip), skip,
"The value must be greater than or equal to zero.");
}
if (take < 0)
{
throw new ArgumentOutOfRangeException(nameof(take), take, "The value must be greater than or equal to zero.");
throw new ArgumentOutOfRangeException(nameof(take), take,
"The value must be greater than or equal to zero.");
}
var results = skip == 0 && take == 0
@@ -264,15 +322,17 @@ namespace Umbraco.Web
}
/// <summary>
/// This is used to contextualize the values in the search results when enumerating over them so that the correct culture values are used
/// This is used to contextualize the values in the search results when enumerating over them so that the correct
/// culture values are used
/// </summary>
private class CultureContextualSearchResults : IEnumerable<PublishedSearchResult>
{
private readonly IEnumerable<PublishedSearchResult> _wrapped;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly string _culture;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IEnumerable<PublishedSearchResult> _wrapped;
public CultureContextualSearchResults(IEnumerable<PublishedSearchResult> wrapped, IVariationContextAccessor variationContextAccessor, string culture)
public CultureContextualSearchResults(IEnumerable<PublishedSearchResult> wrapped,
IVariationContextAccessor variationContextAccessor, string culture)
{
_wrapped = wrapped;
_variationContextAccessor = variationContextAccessor;
@@ -287,24 +347,23 @@ namespace Umbraco.Web
_variationContextAccessor.VariationContext = new VariationContext(_culture);
//now the IPublishedContent returned will be contextualized to the culture specified and will be reset when the enumerator is disposed
return new CultureContextualSearchResultsEnumerator(_wrapped.GetEnumerator(), _variationContextAccessor, originalContext);
return new CultureContextualSearchResultsEnumerator(_wrapped.GetEnumerator(), _variationContextAccessor,
originalContext);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>
/// Resets the variation context when this is disposed
/// Resets the variation context when this is disposed
/// </summary>
private class CultureContextualSearchResultsEnumerator : IEnumerator<PublishedSearchResult>
{
private readonly IEnumerator<PublishedSearchResult> _wrapped;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly VariationContext _originalContext;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IEnumerator<PublishedSearchResult> _wrapped;
public CultureContextualSearchResultsEnumerator(IEnumerator<PublishedSearchResult> wrapped, IVariationContextAccessor variationContextAccessor, VariationContext originalContext)
public CultureContextualSearchResultsEnumerator(IEnumerator<PublishedSearchResult> wrapped,
IVariationContextAccessor variationContextAccessor, VariationContext originalContext)
{
_wrapped = wrapped;
_variationContextAccessor = variationContextAccessor;
@@ -318,10 +377,7 @@ namespace Umbraco.Web
_variationContextAccessor.VariationContext = _originalContext;
}
public bool MoveNext()
{
return _wrapped.MoveNext();
}
public bool MoveNext() => _wrapped.MoveNext();
public void Reset()
{
@@ -6,6 +6,7 @@ using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Web.PublishedCache;
@@ -26,12 +27,14 @@ namespace Umbraco.Web.Routing
private readonly IUmbracoSettingsSection _umbracoSettings;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly IRedirectUrlService _redirectUrlService;
private readonly IVariationContextAccessor _variationContextAccessor;
public RedirectTrackingComponent(IUmbracoSettingsSection umbracoSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService)
public RedirectTrackingComponent(IUmbracoSettingsSection umbracoSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService, IVariationContextAccessor variationContextAccessor)
{
_umbracoSettings = umbracoSettings;
_publishedSnapshotAccessor = publishedSnapshotAccessor;
_redirectUrlService = redirectUrlService;
_variationContextAccessor = variationContextAccessor;
}
public void Initialize()
@@ -99,12 +102,12 @@ namespace Umbraco.Web.Routing
{
var contentCache = _publishedSnapshotAccessor.PublishedSnapshot.Content;
var entityContent = contentCache.GetById(entity.Id);
if (entityContent == null) return;
if (entityContent == null) return;
// get the default affected cultures by going up the tree until we find the first culture variant entity (default to no cultures)
// get the default affected cultures by going up the tree until we find the first culture variant entity (default to no cultures)
var defaultCultures = entityContent.AncestorsOrSelf()?.FirstOrDefault(a => a.Cultures.Any())?.Cultures.Keys.ToArray()
?? new[] { (string)null };
foreach (var x in entityContent.DescendantsOrSelf())
foreach (var x in entityContent.DescendantsOrSelf(_variationContextAccessor))
{
// if this entity defines specific cultures, use those instead of the default ones
var cultures = x.Cultures.Any() ? x.Cultures.Keys : defaultCultures;
@@ -9,6 +9,7 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Request;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
@@ -37,6 +38,7 @@ namespace Umbraco.Web.Scheduling
private readonly IUmbracoSettingsSection _umbracoSettingsSection;
private readonly IIOHelper _ioHelper;
private readonly IServerMessenger _serverMessenger;
private readonly IRequestAccessor _requestAccessor;
private BackgroundTaskRunner<IBackgroundTask> _keepAliveRunner;
private BackgroundTaskRunner<IBackgroundTask> _publishingRunner;
@@ -54,7 +56,7 @@ namespace Umbraco.Web.Scheduling
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger,
IHostingEnvironment hostingEnvironment, IHealthChecks healthChecksConfig,
IUmbracoSettingsSection umbracoSettingsSection, IIOHelper ioHelper, IServerMessenger serverMessenger)
IUmbracoSettingsSection umbracoSettingsSection, IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor)
{
_runtime = runtime;
_contentService = contentService;
@@ -70,6 +72,7 @@ namespace Umbraco.Web.Scheduling
_umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
_ioHelper = ioHelper;
_serverMessenger = serverMessenger;
_requestAccessor = requestAccessor;
}
public void Initialize()
@@ -83,7 +86,7 @@ namespace Umbraco.Web.Scheduling
_healthCheckRunner = new BackgroundTaskRunner<IBackgroundTask>("HealthCheckNotifier", _logger, _hostingEnvironment);
// we will start the whole process when a successful request is made
UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce;
_requestAccessor.RouteAttempt += RegisterBackgroundTasksOnce;
}
public void Terminate()
@@ -97,7 +100,7 @@ namespace Umbraco.Web.Scheduling
{
case EnsureRoutableOutcome.IsRoutable:
case EnsureRoutableOutcome.NotDocumentRequest:
UmbracoModule.RouteAttempt -= RegisterBackgroundTasksOnce;
_requestAccessor.RouteAttempt -= RegisterBackgroundTasksOnce;
RegisterBackgroundTasks();
break;
}
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Sync
// but only processes instructions coming from remote servers,
// thus ensuring that instructions run only once
//
public class DatabaseServerMessenger : ServerMessengerBase
public class DatabaseServerMessenger : ServerMessengerBase, IDatabaseServerMessenger
{
private readonly IRuntimeState _runtime;
private readonly ManualResetEvent _syncIdle;
@@ -126,10 +126,6 @@ namespace Umbraco.Core.Sync
const int weight = 10;
//TODO Why do we have interface if we expect to be exact type!!!?
// if (!(_runtime is RuntimeState runtime))
// throw new NotSupportedException($"Unsupported IRuntimeState implementation {_runtime.GetType().FullName}, expecting {typeof(RuntimeState).FullName}.");
var registered = _runtime.MainDom.Register(
() =>
{
@@ -4,7 +4,6 @@ using System.Linq;
using Newtonsoft.Json;
using Umbraco.Composing;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Sync
@@ -1,4 +1,4 @@
using Umbraco.ModelsBuilder.Embedded.Configuration;
using Umbraco.Core.Configuration;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.ModelsBuilder.Embedded.BackOffice
@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.ModelsBuilder.Embedded.Configuration;
using Umbraco.Web.Editors;
using Umbraco.Web.Models.ContentEditing;
@@ -1,5 +1,6 @@
using System.Text;
using Umbraco.ModelsBuilder.Embedded.Configuration;
using Umbraco.Configuration;
using Umbraco.Core.Configuration;
namespace Umbraco.ModelsBuilder.Embedded.BackOffice
{
@@ -1,4 +1,4 @@
using Umbraco.ModelsBuilder.Embedded.Configuration;
using Umbraco.Core.Configuration;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.ModelsBuilder.Embedded.BackOffice
@@ -1,4 +1,4 @@
using Umbraco.ModelsBuilder.Embedded.Configuration;
using Umbraco.Core.Configuration;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.ModelsBuilder.Embedded.BackOffice

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