Merge branch 'v8/dev' into v8/merge/5061-from-v7
This commit is contained in:
@@ -70,7 +70,23 @@ namespace Umbraco.Core.Composing
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<Type> PrepareComposerTypes()
|
||||
internal IEnumerable<Type> PrepareComposerTypes()
|
||||
{
|
||||
var requirements = GetRequirements();
|
||||
|
||||
// only for debugging, this is verbose
|
||||
//_logger.Debug<Composers>(GetComposersReport(requirements));
|
||||
|
||||
var sortedComposerTypes = SortComposers(requirements);
|
||||
|
||||
// bit verbose but should help for troubleshooting
|
||||
//var text = "Ordered Composers: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComposerTypes) + Environment.NewLine;
|
||||
_logger.Debug<Composers>("Ordered Composers: {SortedComposerTypes}", sortedComposerTypes);
|
||||
|
||||
return sortedComposerTypes;
|
||||
}
|
||||
|
||||
internal Dictionary<Type, List<Type>> GetRequirements(bool throwOnMissing = true)
|
||||
{
|
||||
// create a list, remove those that cannot be enabled due to runtime level
|
||||
var composerTypeList = _composerTypes
|
||||
@@ -89,25 +105,69 @@ namespace Umbraco.Core.Composing
|
||||
// enable or disable composers
|
||||
EnableDisableComposers(composerTypeList);
|
||||
|
||||
// sort the composers according to their dependencies
|
||||
var requirements = new Dictionary<Type, List<Type>>();
|
||||
foreach (var type in composerTypeList) requirements[type] = null;
|
||||
foreach (var type in composerTypeList)
|
||||
void GatherInterfaces<TAttribute>(Type type, Func<TAttribute, Type> getTypeInAttribute, HashSet<Type> iset, List<Type> set2)
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
GatherRequirementsFromRequireAttribute(type, composerTypeList, requirements);
|
||||
GatherRequirementsFromRequiredByAttribute(type, composerTypeList, requirements);
|
||||
foreach (var attribute in type.GetCustomAttributes<TAttribute>())
|
||||
{
|
||||
var typeInAttribute = getTypeInAttribute(attribute);
|
||||
if (typeInAttribute != null && // if the attribute references a type ...
|
||||
typeInAttribute.IsInterface && // ... which is an interface ...
|
||||
typeof(IComposer).IsAssignableFrom(typeInAttribute) && // ... which implements IComposer ...
|
||||
!iset.Contains(typeInAttribute)) // ... which is not already in the list
|
||||
{
|
||||
// add it to the new list
|
||||
iset.Add(typeInAttribute);
|
||||
set2.Add(typeInAttribute);
|
||||
|
||||
// add all its interfaces implementing IComposer
|
||||
foreach (var i in typeInAttribute.GetInterfaces().Where(x => typeof(IComposer).IsAssignableFrom(x)))
|
||||
{
|
||||
iset.Add(i);
|
||||
set2.Add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only for debugging, this is verbose
|
||||
//_logger.Debug<Composers>(GetComposersReport(requirements));
|
||||
// gather interfaces too
|
||||
var interfaces = new HashSet<Type>(composerTypeList.SelectMany(x => x.GetInterfaces().Where(y => typeof(IComposer).IsAssignableFrom(y))));
|
||||
composerTypeList.AddRange(interfaces);
|
||||
var list1 = composerTypeList;
|
||||
while (list1.Count > 0)
|
||||
{
|
||||
var list2 = new List<Type>();
|
||||
foreach (var t in list1)
|
||||
{
|
||||
GatherInterfaces<ComposeAfterAttribute>(t, a => a.RequiredType, interfaces, list2);
|
||||
GatherInterfaces<ComposeBeforeAttribute>(t, a => a.RequiringType, interfaces, list2);
|
||||
}
|
||||
composerTypeList.AddRange(list2);
|
||||
list1 = list2;
|
||||
}
|
||||
|
||||
// sort the composers according to their dependencies
|
||||
var requirements = new Dictionary<Type, List<Type>>();
|
||||
foreach (var type in composerTypeList)
|
||||
requirements[type] = null;
|
||||
foreach (var type in composerTypeList)
|
||||
{
|
||||
GatherRequirementsFromAfterAttribute(type, composerTypeList, requirements, throwOnMissing);
|
||||
GatherRequirementsFromBeforeAttribute(type, composerTypeList, requirements);
|
||||
}
|
||||
|
||||
return requirements;
|
||||
}
|
||||
|
||||
internal IEnumerable<Type> SortComposers(Dictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
// sort composers
|
||||
var graph = new TopoGraph<Type, KeyValuePair<Type, List<Type>>>(kvp => kvp.Key, kvp => kvp.Value);
|
||||
graph.AddItems(requirements);
|
||||
List<Type> sortedComposerTypes;
|
||||
try
|
||||
{
|
||||
sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).ToList();
|
||||
sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).Where(x => !x.IsInterface).ToList();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -117,40 +177,37 @@ namespace Umbraco.Core.Composing
|
||||
throw;
|
||||
}
|
||||
|
||||
// bit verbose but should help for troubleshooting
|
||||
//var text = "Ordered Composers: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComposerTypes) + Environment.NewLine;
|
||||
_logger.Debug<Composers>("Ordered Composers: {SortedComposerTypes}", sortedComposerTypes);
|
||||
|
||||
return sortedComposerTypes;
|
||||
}
|
||||
|
||||
private static string GetComposersReport(Dictionary<Type, List<Type>> requirements)
|
||||
internal static string GetComposersReport(Dictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
var text = new StringBuilder();
|
||||
text.AppendLine("Composers & Dependencies:");
|
||||
text.AppendLine(" < compose before");
|
||||
text.AppendLine(" > compose after");
|
||||
text.AppendLine(" : implements");
|
||||
text.AppendLine(" = depends");
|
||||
text.AppendLine();
|
||||
|
||||
bool HasReq(IEnumerable<Type> types, Type type)
|
||||
=> types.Any(x => type.IsAssignableFrom(x) && !x.IsInterface);
|
||||
|
||||
foreach (var kvp in requirements)
|
||||
{
|
||||
var type = kvp.Key;
|
||||
|
||||
text.AppendLine(type.FullName);
|
||||
foreach (var attribute in type.GetCustomAttributes<ComposeAfterAttribute>())
|
||||
text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue
|
||||
? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")"))
|
||||
: ""));
|
||||
foreach (var attribute in type.GetCustomAttributes<ComposeBeforeAttribute>())
|
||||
text.AppendLine(" -< " + attribute.RequiringType);
|
||||
foreach (var i in type.GetInterfaces())
|
||||
{
|
||||
text.AppendLine(" : " + i.FullName);
|
||||
foreach (var attribute in i.GetCustomAttributes<ComposeAfterAttribute>())
|
||||
text.AppendLine(" -> " + attribute.RequiredType + (attribute.Weak.HasValue
|
||||
? (attribute.Weak.Value ? " (weak)" : (" (strong" + (requirements.ContainsKey(attribute.RequiredType) ? ", missing" : "") + ")"))
|
||||
: ""));
|
||||
foreach (var attribute in i.GetCustomAttributes<ComposeBeforeAttribute>())
|
||||
text.AppendLine(" -< " + attribute.RequiringType);
|
||||
var weak = !(attribute.RequiredType.IsInterface ? attribute.Weak == false : attribute.Weak != true);
|
||||
text.AppendLine(" > " + attribute.RequiredType +
|
||||
(weak ? " (weak" : " (strong") + (HasReq(requirements.Keys, attribute.RequiredType) ? ", found" : ", missing") + ")");
|
||||
}
|
||||
foreach (var attribute in type.GetCustomAttributes<ComposeBeforeAttribute>())
|
||||
text.AppendLine(" < " + attribute.RequiringType);
|
||||
foreach (var i in type.GetInterfaces())
|
||||
text.AppendLine(" : " + i.FullName);
|
||||
if (kvp.Value != null)
|
||||
foreach (var t in kvp.Value)
|
||||
text.AppendLine(" = " + t);
|
||||
@@ -221,16 +278,16 @@ namespace Umbraco.Core.Composing
|
||||
types.Remove(kvp.Key);
|
||||
}
|
||||
|
||||
private static void GatherRequirementsFromRequireAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements)
|
||||
private static void GatherRequirementsFromAfterAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements, bool throwOnMissing = true)
|
||||
{
|
||||
// get 'require' attributes
|
||||
// these attributes are *not* inherited because we want to "custom-inherit" for interfaces only
|
||||
var requireAttributes = type
|
||||
var afterAttributes = type
|
||||
.GetInterfaces().SelectMany(x => x.GetCustomAttributes<ComposeAfterAttribute>()) // those marking interfaces
|
||||
.Concat(type.GetCustomAttributes<ComposeAfterAttribute>()); // those marking the composer
|
||||
|
||||
// what happens in case of conflicting attributes (different strong/weak for same type) is not specified.
|
||||
foreach (var attr in requireAttributes)
|
||||
foreach (var attr in afterAttributes)
|
||||
{
|
||||
if (attr.RequiredType == type) continue; // ignore self-requirements (+ exclude in implems, below)
|
||||
|
||||
@@ -238,13 +295,13 @@ namespace Umbraco.Core.Composing
|
||||
// unless strong, and then require at least one enabled composer implementing that interface
|
||||
if (attr.RequiredType.IsInterface)
|
||||
{
|
||||
var implems = types.Where(x => x != type && attr.RequiredType.IsAssignableFrom(x)).ToList();
|
||||
var implems = types.Where(x => x != type && attr.RequiredType.IsAssignableFrom(x) && !x.IsInterface).ToList();
|
||||
if (implems.Count > 0)
|
||||
{
|
||||
if (requirements[type] == null) requirements[type] = new List<Type>();
|
||||
requirements[type].AddRange(implems);
|
||||
}
|
||||
else if (attr.Weak == false) // if explicitly set to !weak, is strong, else is weak
|
||||
else if (attr.Weak == false && throwOnMissing) // if explicitly set to !weak, is strong, else is weak
|
||||
throw new Exception($"Broken composer dependency: {type.FullName} -> {attr.RequiredType.FullName}.");
|
||||
}
|
||||
// requiring a class = require that the composer is enabled
|
||||
@@ -256,28 +313,28 @@ namespace Umbraco.Core.Composing
|
||||
if (requirements[type] == null) requirements[type] = new List<Type>();
|
||||
requirements[type].Add(attr.RequiredType);
|
||||
}
|
||||
else if (attr.Weak != true) // if not explicitly set to weak, is strong
|
||||
else if (attr.Weak != true && throwOnMissing) // if not explicitly set to weak, is strong
|
||||
throw new Exception($"Broken composer dependency: {type.FullName} -> {attr.RequiredType.FullName}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GatherRequirementsFromRequiredByAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements)
|
||||
private static void GatherRequirementsFromBeforeAttribute(Type type, ICollection<Type> types, IDictionary<Type, List<Type>> requirements)
|
||||
{
|
||||
// get 'required' attributes
|
||||
// these attributes are *not* inherited because we want to "custom-inherit" for interfaces only
|
||||
var requiredAttributes = type
|
||||
var beforeAttributes = type
|
||||
.GetInterfaces().SelectMany(x => x.GetCustomAttributes<ComposeBeforeAttribute>()) // those marking interfaces
|
||||
.Concat(type.GetCustomAttributes<ComposeBeforeAttribute>()); // those marking the composer
|
||||
|
||||
foreach (var attr in requiredAttributes)
|
||||
foreach (var attr in beforeAttributes)
|
||||
{
|
||||
if (attr.RequiringType == type) continue; // ignore self-requirements (+ exclude in implems, below)
|
||||
|
||||
// required by an interface = by any enabled composer implementing this that interface
|
||||
if (attr.RequiringType.IsInterface)
|
||||
{
|
||||
var implems = types.Where(x => x != type && attr.RequiringType.IsAssignableFrom(x)).ToList();
|
||||
var implems = types.Where(x => x != type && attr.RequiringType.IsAssignableFrom(x) && !x.IsInterface).ToList();
|
||||
foreach (var implem in implems)
|
||||
{
|
||||
if (requirements[implem] == null) requirements[implem] = new List<Type>();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
internal class DropDownFlexibleConfiguration : ValueListConfiguration
|
||||
public class DropDownFlexibleConfiguration : ValueListConfiguration
|
||||
{
|
||||
[ConfigurationField("multiple", "Enable multiple choice", "boolean", Description = "When checked, the dropdown will be a select multiple / combo box style dropdown.")]
|
||||
public bool Multiple { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Compose;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -299,11 +300,19 @@ namespace Umbraco.Tests.Components
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
Composed.Clear();
|
||||
Assert.Throws<Exception>(() => composers.Compose());
|
||||
Console.WriteLine("throws:");
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
var requirements = composers.GetRequirements(false);
|
||||
Console.WriteLine(Composers.GetComposersReport(requirements));
|
||||
|
||||
types = new[] { typeof(Composer2) };
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
Composed.Clear();
|
||||
Assert.Throws<Exception>(() => composers.Compose());
|
||||
Console.WriteLine("throws:");
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
requirements = composers.GetRequirements(false);
|
||||
Console.WriteLine(Composers.GetComposersReport(requirements));
|
||||
|
||||
types = new[] { typeof(Composer12) };
|
||||
composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
@@ -349,6 +358,25 @@ namespace Umbraco.Tests.Components
|
||||
Assert.AreEqual(typeof(Composer27), Composed[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllComposers()
|
||||
{
|
||||
var typeLoader = new TypeLoader(AppCaches.Disabled.RuntimeCache, IOHelper.MapPath("~/App_Data/TEMP"), Mock.Of<IProfilingLogger>());
|
||||
|
||||
var register = MockRegister();
|
||||
var composition = new Composition(register, typeLoader, Mock.Of<IProfilingLogger>(), MockRuntimeState(RuntimeLevel.Run));
|
||||
|
||||
var types = typeLoader.GetTypes<IComposer>().Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web"));
|
||||
var composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
|
||||
var requirements = composers.GetRequirements();
|
||||
var report = Composers.GetComposersReport(requirements);
|
||||
Console.WriteLine(report);
|
||||
var composerTypes = composers.SortComposers(requirements);
|
||||
|
||||
foreach (var type in composerTypes)
|
||||
Console.WriteLine(type);
|
||||
}
|
||||
|
||||
#region Compothings
|
||||
|
||||
public class TestComposerBase : IComposer
|
||||
|
||||
@@ -381,6 +381,9 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
}
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi nodeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return GetXml(preview).CreateNavigator().MoveToId(contentId.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
@@ -97,6 +97,9 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi nodeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return GetUmbracoMedia(contentId) != null;
|
||||
|
||||
@@ -92,6 +92,9 @@ namespace Umbraco.Tests.PublishedContent
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi nodeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
return _content.ContainsKey(contentId);
|
||||
|
||||
@@ -228,40 +228,64 @@ body.touch .umb-tree {
|
||||
}
|
||||
}
|
||||
|
||||
.umb-tree-item__annotation {
|
||||
&::before {
|
||||
font-family: 'icomoon';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
.has-unpublished-version, .is-container, .protected {
|
||||
> .umb-tree-item__inner {
|
||||
> .umb-tree-item__annotation {
|
||||
background-color: @white;
|
||||
border-radius: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
position: absolute;
|
||||
margin-left: 12px;
|
||||
top: 17px;
|
||||
|
||||
.has-unpublished-version > .umb-tree-item__inner > .umb-tree-item__annotation::before {
|
||||
content: "\e25a";
|
||||
color: @green;
|
||||
font-size: 20px;
|
||||
margin-left: -25px;
|
||||
&::before {
|
||||
font-family: 'icomoon';
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover > .umb-tree-item__annotation {
|
||||
background-color: @ui-option-hover;
|
||||
}
|
||||
}
|
||||
|
||||
&.current > .umb-tree-item__inner > .umb-tree-item__annotation {
|
||||
background-color: @pinkLight;
|
||||
}
|
||||
}
|
||||
|
||||
.is-container > .umb-tree-item__inner > .umb-tree-item__annotation::before {
|
||||
content: "\e04e";
|
||||
color: @blue;
|
||||
font-size: 9px;
|
||||
margin-left: -20px;
|
||||
margin-left: 2px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.has-unpublished-version > .umb-tree-item__inner > .umb-tree-item__annotation::before {
|
||||
content: "\e25a";
|
||||
color: @green;
|
||||
font-size: 23px;
|
||||
margin-left: 16px;
|
||||
left: -21px;
|
||||
}
|
||||
|
||||
.protected > .umb-tree-item__inner > .umb-tree-item__annotation::before {
|
||||
content: "\e256";
|
||||
color: @red;
|
||||
font-size: 20px;
|
||||
margin-left: -25px;
|
||||
font-size: 23px;
|
||||
margin-left: -3px;
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
.locked > .umb-tree-item__inner > .umb-tree-item__annotation::before {
|
||||
content: "\e0a7";
|
||||
color: @red;
|
||||
font-size: 9px;
|
||||
margin-left: -20px;
|
||||
margin-left: 2px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.no-access {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Xml;
|
||||
|
||||
@@ -29,6 +30,15 @@ namespace Umbraco.Web.PublishedCache
|
||||
/// <remarks>The value of <paramref name="preview"/> overrides defaults.</remarks>
|
||||
IPublishedContent GetById(bool preview, Guid contentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a content identified by its Udi identifier.
|
||||
/// </summary>
|
||||
/// <param name="preview">A value indicating whether to consider unpublished content.</param>
|
||||
/// <param name="contentId">The content Udi identifier.</param>
|
||||
/// <returns>The content, or null.</returns>
|
||||
/// <remarks>The value of <paramref name="preview"/> overrides defaults.</remarks>
|
||||
IPublishedContent GetById(bool preview, Udi contentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a content identified by its unique identifier.
|
||||
/// </summary>
|
||||
@@ -45,6 +55,14 @@ namespace Umbraco.Web.PublishedCache
|
||||
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
|
||||
IPublishedContent GetById(Guid contentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a content identified by its unique identifier.
|
||||
/// </summary>
|
||||
/// <param name="contentId">The content unique identifier.</param>
|
||||
/// <returns>The content, or null.</returns>
|
||||
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
|
||||
IPublishedContent GetById(Udi contentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the cache contains a specified content.
|
||||
/// </summary>
|
||||
|
||||
@@ -238,6 +238,18 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return GetNodePublishedContent(node, preview);
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi contentId)
|
||||
{
|
||||
var guidUdi = contentId as GuidUdi;
|
||||
if (guidUdi == null)
|
||||
throw new ArgumentException($"Udi must be of type {typeof(GuidUdi).Name}.", nameof(contentId));
|
||||
|
||||
if (guidUdi.EntityType != Constants.UdiEntityType.Document)
|
||||
throw new ArgumentException($"Udi entity type must be \"{Constants.UdiEntityType.Document}\".", nameof(contentId));
|
||||
|
||||
return GetById(preview, guidUdi.Guid);
|
||||
}
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
var n = _snapshot.Get(contentId);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Xml;
|
||||
@@ -44,6 +45,20 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return n?.PublishedModel;
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Udi contentId)
|
||||
{
|
||||
var guidUdi = contentId as GuidUdi;
|
||||
if (guidUdi == null)
|
||||
throw new ArgumentException($"Udi must be of type {typeof(GuidUdi).Name}.", nameof(contentId));
|
||||
|
||||
if (guidUdi.EntityType != Constants.UdiEntityType.Media)
|
||||
throw new ArgumentException($"Udi entity type must be \"{Constants.UdiEntityType.Media}\".", nameof(contentId));
|
||||
|
||||
// ignore preview, there's only draft for media
|
||||
var n = _snapshot.Get(guidUdi.Guid);
|
||||
return n?.PublishedModel;
|
||||
}
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
{
|
||||
var n = _snapshot.Get(contentId);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Xml;
|
||||
|
||||
@@ -19,23 +20,22 @@ namespace Umbraco.Web.PublishedCache
|
||||
public abstract IPublishedContent GetById(bool preview, int contentId);
|
||||
|
||||
public IPublishedContent GetById(int contentId)
|
||||
{
|
||||
return GetById(PreviewDefault, contentId);
|
||||
}
|
||||
=> GetById(PreviewDefault, contentId);
|
||||
|
||||
public abstract IPublishedContent GetById(bool preview, Guid contentId);
|
||||
|
||||
public IPublishedContent GetById(Guid contentId)
|
||||
{
|
||||
return GetById(PreviewDefault, contentId);
|
||||
}
|
||||
=> GetById(PreviewDefault, contentId);
|
||||
|
||||
public abstract IPublishedContent GetById(bool preview, Udi contentId);
|
||||
|
||||
public IPublishedContent GetById(Udi contentId)
|
||||
=> GetById(PreviewDefault, contentId);
|
||||
|
||||
public abstract bool HasById(bool preview, int contentId);
|
||||
|
||||
public bool HasById(int contentId)
|
||||
{
|
||||
return HasById(PreviewDefault, contentId);
|
||||
}
|
||||
=> HasById(PreviewDefault, contentId);
|
||||
|
||||
public abstract IEnumerable<IPublishedContent> GetAtRoot(bool preview);
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
// web's final composer composes after all user composers
|
||||
// and *also* after ICoreComposer (in case IUserComposer is disabled)
|
||||
[ComposeAfter(typeof(IUserComposer))]
|
||||
[ComposeAfter(typeof(ICoreComposer))]
|
||||
public class WebFinalComposer : ComponentComposer<WebFinalComponent>
|
||||
{ }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user