8.7RC Add generic BlockListItem classes (#8841)

(cherry picked from commit 5faa9ae22f)
This commit is contained in:
Ronald Barendse
2020-09-08 12:08:27 +02:00
committed by Sebastiaan Janssen
parent bb30b17fe2
commit ddc922a583
5 changed files with 173 additions and 86 deletions

View File

@@ -5,41 +5,126 @@ using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.Models.Blocks
{
/// <summary>
/// Represents a layout item for the Block List editor
/// Represents a layout item for the Block List editor.
/// </summary>
/// <seealso cref="Umbraco.Core.Models.Blocks.IBlockReference{Umbraco.Core.Models.PublishedContent.IPublishedElement}" />
[DataContract(Name = "block", Namespace = "")]
public class BlockListItem : IBlockReference<IPublishedElement>
{
/// <summary>
/// Initializes a new instance of the <see cref="BlockListItem" /> class.
/// </summary>
/// <param name="contentUdi">The content UDI.</param>
/// <param name="content">The content.</param>
/// <param name="settingsUdi">The settings UDI.</param>
/// <param name="settings">The settings.</param>
/// <exception cref="System.ArgumentNullException">contentUdi
/// or
/// content</exception>
public BlockListItem(Udi contentUdi, IPublishedElement content, Udi settingsUdi, IPublishedElement settings)
{
ContentUdi = contentUdi ?? throw new ArgumentNullException(nameof(contentUdi));
ContentUdi = contentUdi ?? throw new ArgumentNullException(nameof(contentUdi));
Content = content ?? throw new ArgumentNullException(nameof(content));
Settings = settings; // can be null
SettingsUdi = settingsUdi; // can be null
SettingsUdi = settingsUdi;
Settings = settings;
}
/// <summary>
/// The Id of the content data item
/// Gets the content UDI.
/// </summary>
/// <value>
/// The content UDI.
/// </value>
[DataMember(Name = "contentUdi")]
public Udi ContentUdi { get; }
/// <summary>
/// The Id of the settings data item
/// </summary>
[DataMember(Name = "settingsUdi")]
public Udi SettingsUdi { get; }
/// <summary>
/// The content data item referenced
/// Gets the content.
/// </summary>
/// <value>
/// The content.
/// </value>
[DataMember(Name = "content")]
public IPublishedElement Content { get; }
/// <summary>
/// The settings data item referenced
/// Gets the settings UDI.
/// </summary>
/// <value>
/// The settings UDI.
/// </value>
[DataMember(Name = "settingsUdi")]
public Udi SettingsUdi { get; }
/// <summary>
/// Gets the settings.
/// </summary>
/// <value>
/// The settings.
/// </value>
[DataMember(Name = "settings")]
public IPublishedElement Settings { get; }
}
/// <summary>
/// Represents a layout item with a generic content type for the Block List editor.
/// </summary>
/// <typeparam name="T">The type of the content.</typeparam>
/// <seealso cref="Umbraco.Core.Models.Blocks.IBlockReference{Umbraco.Core.Models.PublishedContent.IPublishedElement}" />
public class BlockListItem<T> : BlockListItem
where T : IPublishedElement
{
/// <summary>
/// Initializes a new instance of the <see cref="BlockListItem{T}" /> class.
/// </summary>
/// <param name="contentUdi">The content UDI.</param>
/// <param name="content">The content.</param>
/// <param name="settingsUdi">The settings UDI.</param>
/// <param name="settings">The settings.</param>
public BlockListItem(Udi contentUdi, T content, Udi settingsUdi, IPublishedElement settings)
: base(contentUdi, content, settingsUdi, settings)
{
Content = content;
}
/// <summary>
/// Gets the content.
/// </summary>
/// <value>
/// The content.
/// </value>
public new T Content { get; }
}
/// <summary>
/// Represents a layout item with generic content and settings types for the Block List editor.
/// </summary>
/// <typeparam name="TContent">The type of the content.</typeparam>
/// <typeparam name="TSettings">The type of the settings.</typeparam>
/// <seealso cref="Umbraco.Core.Models.Blocks.IBlockReference{Umbraco.Core.Models.PublishedContent.IPublishedElement}" />
public class BlockListItem<TContent, TSettings> : BlockListItem<TContent>
where TContent : IPublishedElement
where TSettings : IPublishedElement
{
/// <summary>
/// Initializes a new instance of the <see cref="BlockListItem{TContent, TSettings}" /> class.
/// </summary>
/// <param name="contentUdi">The content udi.</param>
/// <param name="content">The content.</param>
/// <param name="settingsUdi">The settings udi.</param>
/// <param name="settings">The settings.</param>
public BlockListItem(Udi contentUdi, TContent content, Udi settingsUdi, TSettings settings)
: base(contentUdi, content, settingsUdi, settings)
{
Settings = settings;
}
/// <summary>
/// Gets the settings.
/// </summary>
/// <value>
/// The settings.
/// </value>
public new TSettings Settings { get; }
}
}

View File

@@ -1,64 +1,63 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.Models.Blocks
{
/// <summary>
/// The strongly typed model for the Block List editor
/// The strongly typed model for the Block List editor.
/// </summary>
/// <seealso cref="System.Collections.ObjectModel.ReadOnlyCollection{Umbraco.Core.Models.Blocks.BlockListItem}" />
[DataContract(Name = "blockList", Namespace = "")]
public class BlockListModel : IReadOnlyList<BlockListItem>
public class BlockListModel : ReadOnlyCollection<BlockListItem>
{
private readonly IReadOnlyList<BlockListItem> _layout = new List<BlockListItem>();
/// <summary>
/// Gets the empty <see cref="BlockListModel" />.
/// </summary>
/// <value>
/// The empty <see cref="BlockListModel" />.
/// </value>
public static BlockListModel Empty { get; } = new BlockListModel();
/// <summary>
/// Prevents a default instance of the <see cref="BlockListModel" /> class from being created.
/// </summary>
private BlockListModel()
{
}
public BlockListModel(IEnumerable<BlockListItem> layout)
{
_layout = layout.ToList();
}
public int Count => _layout.Count;
: this(new List<BlockListItem>())
{ }
/// <summary>
/// Get the block by index
/// Initializes a new instance of the <see cref="BlockListModel" /> class.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public BlockListItem this[int index] => _layout[index];
/// <param name="list">The list to wrap.</param>
public BlockListModel(IList<BlockListItem> list)
: base(list)
{ }
/// <summary>
/// Get the block by content Guid
/// Gets the <see cref="BlockListItem" /> with the specified content key.
/// </summary>
/// <param name="contentKey"></param>
/// <returns></returns>
public BlockListItem this[Guid contentKey] => _layout.FirstOrDefault(x => x.Content.Key == contentKey);
/// <value>
/// The <see cref="BlockListItem" />.
/// </value>
/// <param name="contentKey">The content key.</param>
/// <returns>
/// The <see cref="BlockListItem" /> with the specified content key.
/// </returns>
public BlockListItem this[Guid contentKey] => this.FirstOrDefault(x => x.Content.Key == contentKey);
/// <summary>
/// Get the block by content element Udi
/// Gets the <see cref="BlockListItem" /> with the specified content UDI.
/// </summary>
/// <param name="contentUdi"></param>
/// <returns></returns>
public BlockListItem this[Udi contentUdi]
{
get
{
if (!(contentUdi is GuidUdi guidUdi)) return null;
return _layout.FirstOrDefault(x => x.Content.Key == guidUdi.Guid);
}
}
public IEnumerator<BlockListItem> GetEnumerator() => _layout.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <value>
/// The <see cref="BlockListItem" />.
/// </value>
/// <param name="contentUdi">The content UDI.</param>
/// <returns>
/// The <see cref="BlockListItem" /> with the specified content UDI.
/// </returns>
public BlockListItem this[Udi contentUdi] => contentUdi is GuidUdi guidUdi ? this.FirstOrDefault(x => x.Content.Key == guidUdi.Guid) : null;
}
}

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using System;
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Models.Blocks
{
@@ -12,26 +12,16 @@ namespace Umbraco.Core.Models.Blocks
}
public Udi ContentUdi { get; }
public Udi SettingsUdi { get; }
public override bool Equals(object obj)
{
return obj is ContentAndSettingsReference reference && Equals(reference);
}
public override bool Equals(object obj) => obj is ContentAndSettingsReference reference && Equals(reference);
public bool Equals(ContentAndSettingsReference other)
{
return EqualityComparer<Udi>.Default.Equals(ContentUdi, other.ContentUdi) &&
EqualityComparer<Udi>.Default.Equals(SettingsUdi, other.SettingsUdi);
}
public bool Equals(ContentAndSettingsReference other) => other != null
&& EqualityComparer<Udi>.Default.Equals(ContentUdi, other.ContentUdi)
&& EqualityComparer<Udi>.Default.Equals(SettingsUdi, other.SettingsUdi);
public override int GetHashCode()
{
var hashCode = 272556606;
hashCode = hashCode * -1521134295 + EqualityComparer<Udi>.Default.GetHashCode(ContentUdi);
hashCode = hashCode * -1521134295 + EqualityComparer<Udi>.Default.GetHashCode(SettingsUdi);
return hashCode;
}
public override int GetHashCode() => (ContentUdi, SettingsUdi).GetHashCode();
public static bool operator ==(ContentAndSettingsReference left, ContentAndSettingsReference right)
{

View File

@@ -1,26 +1,37 @@
namespace Umbraco.Core.Models.Blocks
{
/// <summary>
/// Represents a data item reference for a Block editor implementation
/// </summary>
/// <typeparam name="TSettings"></typeparam>
/// <remarks>
/// see: https://github.com/umbraco/rfcs/blob/907f3758cf59a7b6781296a60d57d537b3b60b8c/cms/0011-block-data-structure.md#strongly-typed
/// </remarks>
public interface IBlockReference<TSettings> : IBlockReference
{
TSettings Settings { get; }
}
/// <summary>
/// Represents a data item reference for a Block Editor implementation
/// Represents a data item reference for a Block Editor implementation.
/// </summary>
/// <remarks>
/// see: https://github.com/umbraco/rfcs/blob/907f3758cf59a7b6781296a60d57d537b3b60b8c/cms/0011-block-data-structure.md#strongly-typed
/// See: https://github.com/umbraco/rfcs/blob/907f3758cf59a7b6781296a60d57d537b3b60b8c/cms/0011-block-data-structure.md#strongly-typed
/// </remarks>
public interface IBlockReference
{
/// <summary>
/// Gets the content UDI.
/// </summary>
/// <value>
/// The content UDI.
/// </value>
Udi ContentUdi { get; }
}
/// <summary>
/// Represents a data item reference with settings for a Block editor implementation.
/// </summary>
/// <typeparam name="TSettings">The type of the settings.</typeparam>
/// <remarks>
/// See: https://github.com/umbraco/rfcs/blob/907f3758cf59a7b6781296a60d57d537b3b60b8c/cms/0011-block-data-structure.md#strongly-typed
/// </remarks>
public interface IBlockReference<TSettings> : IBlockReference
{
/// <summary>
/// Gets the settings.
/// </summary>
/// <value>
/// The settings.
/// </value>
TSettings Settings { get; }
}
}

View File

@@ -120,7 +120,9 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
settingsData = null;
}
var layoutRef = new BlockListItem(contentGuidUdi, contentData, settingGuidUdi, settingsData);
var layoutType = typeof(BlockListItem<,>).MakeGenericType(contentData.GetType(), settingsData?.GetType() ?? typeof(IPublishedElement));
var layoutRef = (BlockListItem)Activator.CreateInstance(layoutType, contentGuidUdi, contentData, settingGuidUdi, settingsData);
layout.Add(layoutRef);
}