Various fixes
This commit is contained in:
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Components
|
||||
text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue
|
||||
? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")"))
|
||||
: ""));
|
||||
foreach (var attribute in type.GetCustomAttributes<RequiredComponentAttribute>())
|
||||
foreach (var attribute in type.GetCustomAttributes<RequiredByComponentAttribute>())
|
||||
text.AppendLine(" -< " + attribute.RequiringType);
|
||||
foreach (var i in type.GetInterfaces())
|
||||
{
|
||||
@@ -144,7 +144,7 @@ namespace Umbraco.Core.Components
|
||||
text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue
|
||||
? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")"))
|
||||
: ""));
|
||||
foreach (var attribute in i.GetCustomAttributes<RequiredComponentAttribute>())
|
||||
foreach (var attribute in i.GetCustomAttributes<RequiredByComponentAttribute>())
|
||||
text.AppendLine(" -< " + attribute.RequiringType);
|
||||
}
|
||||
if (kvp.Value != null)
|
||||
@@ -221,7 +221,7 @@ namespace Umbraco.Core.Components
|
||||
if (requirements[type] == null) requirements[type] = new List<Type>();
|
||||
requirements[type].AddRange(implems);
|
||||
}
|
||||
else if (attr.Weak == false) // if explicitely set to !weak, is strong, else is weak
|
||||
else if (attr.Weak == false) // if explicitly set to !weak, is strong, else is weak
|
||||
throw new Exception($"Broken component dependency: {type.FullName} -> {attr.RequiredType.FullName}.");
|
||||
}
|
||||
// requiring a class = require that the component is enabled
|
||||
@@ -233,7 +233,7 @@ namespace Umbraco.Core.Components
|
||||
if (requirements[type] == null) requirements[type] = new List<Type>();
|
||||
requirements[type].Add(attr.RequiredType);
|
||||
}
|
||||
else if (attr.Weak != true) // if not explicitely set to weak, is strong
|
||||
else if (attr.Weak != true) // if not explicitly set to weak, is strong
|
||||
throw new Exception($"Broken component dependency: {type.FullName} -> {attr.RequiredType.FullName}.");
|
||||
}
|
||||
}
|
||||
@@ -244,8 +244,8 @@ namespace Umbraco.Core.Components
|
||||
// get 'required' attributes
|
||||
// these attributes are *not* inherited because we want to "custom-inherit" for interfaces only
|
||||
var requiredAttributes = type
|
||||
.GetInterfaces().SelectMany(x => x.GetCustomAttributes<RequiredComponentAttribute>()) // those marking interfaces
|
||||
.Concat(type.GetCustomAttributes<RequiredComponentAttribute>()); // those marking the component
|
||||
.GetInterfaces().SelectMany(x => x.GetCustomAttributes<RequiredByComponentAttribute>()) // those marking interfaces
|
||||
.Concat(type.GetCustomAttributes<RequiredByComponentAttribute>()); // those marking the component
|
||||
|
||||
foreach (var attr in requiredAttributes)
|
||||
{
|
||||
@@ -275,7 +275,7 @@ namespace Umbraco.Core.Components
|
||||
|
||||
private void InstantiateComponents(IEnumerable<Type> types)
|
||||
{
|
||||
using (_proflog.DebugDuration<BootLoader>("Instanciating components.", "Instanciated components."))
|
||||
using (_proflog.DebugDuration<BootLoader>("Instantiating components.", "Instantiated components."))
|
||||
{
|
||||
_components = types.Select(x => (IUmbracoComponent) Activator.CreateInstance(x)).ToArray();
|
||||
}
|
||||
@@ -309,7 +309,7 @@ namespace Umbraco.Core.Components
|
||||
var componentType = component.GetType();
|
||||
var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Where(x => x.Name == "Initialize" && x.IsGenericMethod == false && x.IsStatic == false);
|
||||
using (_proflog.DebugDuration<BootLoader>($"Initializing {componentType.FullName}.", $"Initialised {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds))
|
||||
using (_proflog.DebugDuration<BootLoader>($"Initializing {componentType.FullName}.", $"Initialized {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds))
|
||||
{
|
||||
foreach (var initializer in initializers)
|
||||
{
|
||||
|
||||
@@ -19,13 +19,13 @@ namespace Umbraco.Core.Components
|
||||
/// </remarks>
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
|
||||
public class RequiredComponentAttribute : Attribute
|
||||
public class RequiredByComponentAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequiredComponentAttribute"/> class.
|
||||
/// Initializes a new instance of the <see cref="RequiredByComponentAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="requiringType">The type of the required component.</param>
|
||||
public RequiredComponentAttribute(Type requiringType)
|
||||
public RequiredByComponentAttribute(Type requiringType)
|
||||
{
|
||||
if (typeof(IUmbracoComponent).IsAssignableFrom(requiringType) == false)
|
||||
throw new ArgumentException($"Type {requiringType.FullName} is invalid here because it does not implement {typeof(IUmbracoComponent).FullName}.");
|
||||
@@ -50,10 +50,6 @@ namespace Umbraco.Core.Composing
|
||||
if (container == null)
|
||||
throw new Exception($"Container factory '{configuredTypeName}' did not return an IContainer implementation.");
|
||||
|
||||
// self-register the container - this is where it should happen
|
||||
// but - we do NOT want to do it!
|
||||
//container.RegisterInstance(container);
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Composing.LightInject;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
|
||||
@@ -14,7 +14,6 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Logging.Serilog;
|
||||
using Umbraco.Core.Migrations.Upgrade;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Scoping;
|
||||
@@ -32,16 +31,11 @@ namespace Umbraco.Core.Runtime
|
||||
private BootLoader _bootLoader;
|
||||
private RuntimeState _state;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CoreRuntime"/> class.
|
||||
/// </summary>
|
||||
public CoreRuntime()
|
||||
{ }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void Boot(IContainer container)
|
||||
{
|
||||
container.ConfigureUmbracoCore(); // also sets Current.Container
|
||||
// assign current container
|
||||
Current.Container = container;
|
||||
|
||||
// register the essential stuff,
|
||||
// ie the global application logger
|
||||
@@ -109,13 +103,6 @@ namespace Umbraco.Core.Runtime
|
||||
// throw a BootFailedException for every requests.
|
||||
}
|
||||
}
|
||||
|
||||
//fixme
|
||||
// after Umbraco has started there is a scope in "context" and that context is
|
||||
// going to stay there and never get destroyed nor reused, so we have to ensure that
|
||||
// everything is cleared
|
||||
//var sa = container.GetInstance<IDatabaseScopeAccessor>();
|
||||
//sa.Scope?.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
<Compile Include="Components\IUmbracoCoreComponent.cs" />
|
||||
<Compile Include="Components\IUmbracoUserComponent.cs" />
|
||||
<Compile Include="Components\RequireComponentAttribute.cs" />
|
||||
<Compile Include="Components\RequiredComponentAttribute.cs" />
|
||||
<Compile Include="Components\RequiredByComponentAttribute.cs" />
|
||||
<Compile Include="Components\RuntimeLevelAttribute.cs" />
|
||||
<Compile Include="Components\UmbracoComponentBase.cs" />
|
||||
<Compile Include="Components\UmbracoCoreComponentBase.cs" />
|
||||
|
||||
@@ -296,7 +296,7 @@ namespace Umbraco.Tests.Components
|
||||
public class Component12 : TestComponentBase, IUmbracoCoreComponent
|
||||
{ }
|
||||
|
||||
[RequiredComponent(typeof(Component1))]
|
||||
[RequiredByComponent(typeof(Component1))]
|
||||
public class Component13 : TestComponentBase
|
||||
{ }
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace Umbraco.Tests.Components
|
||||
public class Component20 : TestComponentBase
|
||||
{ }
|
||||
|
||||
[RequiredComponent(typeof(Component20))]
|
||||
[RequiredByComponent(typeof(Component20))]
|
||||
public class Component21 : TestComponentBase
|
||||
{ }
|
||||
|
||||
@@ -322,7 +322,7 @@ namespace Umbraco.Tests.Components
|
||||
{ }
|
||||
|
||||
// should insert itself between 22 and anything i23
|
||||
[RequiredComponent(typeof(IComponent23))]
|
||||
[RequiredByComponent(typeof(IComponent23))]
|
||||
//[RequireComponent(typeof(Component22))] - not needed, implement i23
|
||||
public class Component25 : TestComponentBase, IComponent23
|
||||
{ }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -55,7 +56,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var stylesheet = new Stylesheet("test-add.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
//Assert
|
||||
Assert.That(_fileSystem.FileExists("test-add.css"), Is.True);
|
||||
@@ -73,12 +74,12 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
var stylesheetUpdate = repository.Get("test-update.css");
|
||||
stylesheetUpdate.Content = "body { color:#000; }";
|
||||
repository.Save(stylesheetUpdate);
|
||||
|
||||
|
||||
|
||||
var stylesheetUpdated = repository.Get("test-update.css");
|
||||
|
||||
@@ -100,12 +101,12 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
stylesheet.AddProperty(new StylesheetProperty("Test", "p", "font-size:2em;"));
|
||||
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
//re-get
|
||||
stylesheet = repository.Get(stylesheet.Name);
|
||||
@@ -127,7 +128,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var stylesheet = new Stylesheet("test-update.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
stylesheet.AddProperty(new StylesheetProperty("Test", "p", "font-size:2em;"));
|
||||
|
||||
@@ -146,10 +147,10 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
// Act
|
||||
var stylesheet = new Stylesheet("test-delete.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
repository.Delete(stylesheet);
|
||||
|
||||
|
||||
|
||||
//Assert
|
||||
Assert.That(_fileSystem.FileExists("test-delete.css"), Is.False);
|
||||
@@ -185,7 +186,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var stylesheets = repository.GetMany();
|
||||
@@ -208,7 +209,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var stylesheet = new Stylesheet("styles-v2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
|
||||
// Act
|
||||
var stylesheets = repository.GetMany("styles-v2.css", "styles.css");
|
||||
@@ -248,14 +249,14 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
var stylesheet = new Stylesheet("test-path-1.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
Assert.IsTrue(_fileSystem.FileExists("test-path-1.css"));
|
||||
Assert.AreEqual("test-path-1.css", stylesheet.Path);
|
||||
Assert.AreEqual("/css/test-path-1.css", stylesheet.VirtualPath);
|
||||
|
||||
stylesheet = new Stylesheet("path-2/test-path-2.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-2.css"));
|
||||
Assert.AreEqual("path-2\\test-path-2.css", stylesheet.Path); // fixed in 7.3 - 7.2.8 does not update the path
|
||||
Assert.AreEqual("/css/path-2/test-path-2.css", stylesheet.VirtualPath);
|
||||
@@ -267,7 +268,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
|
||||
stylesheet = new Stylesheet("path-2\\test-path-3.css") { Content = "body { color:#000; } .bold {font-weight:bold;}" };
|
||||
repository.Save(stylesheet);
|
||||
|
||||
|
||||
Assert.IsTrue(_fileSystem.FileExists("path-2/test-path-3.css"));
|
||||
Assert.AreEqual("path-2\\test-path-3.css", stylesheet.Path);
|
||||
Assert.AreEqual("/css/path-2/test-path-3.css", stylesheet.VirtualPath);
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -11,16 +7,11 @@ using Umbraco.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Web.Actions
|
||||
{
|
||||
public class ActionCollection : IBuilderCollection<IAction>
|
||||
public class ActionCollection : BuilderCollectionBase<IAction>
|
||||
{
|
||||
private Func<IEnumerable<Type>> _producer;
|
||||
private readonly object _locker = new object();
|
||||
private IAction[] _items;
|
||||
|
||||
internal ActionCollection(Func<IEnumerable<Type>> producer)
|
||||
{
|
||||
_producer = producer;
|
||||
}
|
||||
public ActionCollection(IEnumerable<IAction> items)
|
||||
: base(items)
|
||||
{ }
|
||||
|
||||
internal T GetAction<T>()
|
||||
where T : IAction
|
||||
@@ -30,66 +21,19 @@ namespace Umbraco.Web.Actions
|
||||
|
||||
internal IEnumerable<IAction> GetByLetters(IEnumerable<string> letters)
|
||||
{
|
||||
var all = this.ToArray();
|
||||
return letters.Select(x => all.FirstOrDefault(y => y.Letter.ToString(CultureInfo.InvariantCulture) == x))
|
||||
return letters
|
||||
.Where(x => x.Length == 1)
|
||||
.Select(x => this.FirstOrDefault(y => y.Letter == x[0]))
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private IAction[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_items != null) return _items;
|
||||
// fixme
|
||||
// why is this not a builder collection base anymore?
|
||||
//
|
||||
var actions = new List<IAction>();
|
||||
foreach (var type in _producer())
|
||||
{
|
||||
var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
|
||||
var instance = getter == null
|
||||
? Activator.CreateInstance(type) as IAction
|
||||
: getter.GetValue(null, null) as IAction;
|
||||
if (instance == null) continue;
|
||||
actions.Add(instance);
|
||||
}
|
||||
|
||||
return _items = actions.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Reset(Func<IEnumerable<Type>> producer)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
_items = null;
|
||||
_producer = producer;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => Items.Length;
|
||||
|
||||
public IEnumerator<IAction> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<IAction>) Items).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
internal IReadOnlyList<IAction> FromEntityPermission(EntityPermission entityPermission)
|
||||
{
|
||||
return entityPermission.AssignedPermissions
|
||||
.Where(x => x.Length == 1)
|
||||
.Select(x => x.ToCharArray()[0])
|
||||
.SelectMany(c => this.Where(x => x.Letter == c))
|
||||
.Where(action => action != null)
|
||||
.SelectMany(x => this.Where(y => y.Letter == x[0]))
|
||||
.WhereNotNull()
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using LightInject;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
|
||||
namespace Umbraco.Web.Actions
|
||||
{
|
||||
internal class ActionCollectionBuilder : LazyCollectionBuilderBase<ActionCollectionBuilder, ActionCollection, IAction>
|
||||
{
|
||||
public ActionCollectionBuilder(IServiceContainer container)
|
||||
public ActionCollectionBuilder(IContainer container)
|
||||
: base(container)
|
||||
{ }
|
||||
|
||||
protected override ActionCollectionBuilder This => this;
|
||||
|
||||
protected override IEnumerable<IAction> CreateItems(params object[] args)
|
||||
protected override IEnumerable<IAction> CreateItems()
|
||||
{
|
||||
var items = base.CreateItems(args).ToList();
|
||||
var items = base.CreateItems().ToList();
|
||||
|
||||
//validate the items, no actions should exist that do not either expose notifications or permissions
|
||||
var invalid = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList();
|
||||
if (invalid.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid actions '{string.Join(", ", invalid.Select(x => x.Alias))}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}");
|
||||
}
|
||||
return items;
|
||||
var invalidItems = items.Where(x => !x.CanBePermissionAssigned && !x.ShowInNotifier).ToList();
|
||||
if (invalidItems.Count == 0) return items;
|
||||
|
||||
var invalidActions = string.Join(", ", invalidItems.Select(x => "'" + x.Alias + "'"));
|
||||
throw new InvalidOperationException($"Invalid actions {invalidActions}'. All {typeof(IAction)} implementations must be true for either {nameof(IAction.CanBePermissionAssigned)} or {nameof(IAction.ShowInNotifier)}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Umbraco.Web.Cache
|
||||
/// Installs listeners on service events in order to refresh our caches.
|
||||
/// </summary>
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
[RequiredComponent(typeof(IUmbracoCoreComponent))] // runs before every other IUmbracoCoreComponent!
|
||||
[RequiredByComponent(typeof(IUmbracoCoreComponent))] // runs before every other IUmbracoCoreComponent!
|
||||
public class CacheRefresherComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, MethodInfo> FoundHandlers = new ConcurrentDictionary<string, MethodInfo>();
|
||||
|
||||
@@ -58,12 +58,9 @@ namespace Umbraco.Web
|
||||
{
|
||||
// ******** THIS IS WHERE EVERYTHING BEGINS ********
|
||||
|
||||
// create the container for the application, and configure.
|
||||
// create the container for the application, and boot
|
||||
// the boot manager is responsible for registrations
|
||||
var container = GetContainer();
|
||||
Current.Container = container; // fixme NOT HERE OR WHAT?
|
||||
|
||||
// get runtime & boot
|
||||
_runtime = GetRuntime();
|
||||
_runtime.Boot(container);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Runtime;
|
||||
using Umbraco.Web.Security;
|
||||
using LightInject;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user