Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup IContentManager #16077

Merged
merged 22 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public async Task<IActionResult> SearchContentItems(string part, string field, s
});

var contentItems = await _contentManager
.GetAsync(results.Select(r => r.ContentItemId));
.GetAsync(results.Select(r => r.ContentItemId), VersionOptions.Published);
Piedone marked this conversation as resolved.
Show resolved Hide resolved

var selectedItems = new List<VueMultiselectItemViewModel>();
foreach (var contentItem in contentItems)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
@model OrchardCore.ContentFields.ViewModels.DisplayContentPickerFieldViewModel
@using OrchardCore.ContentManagement
@using OrchardCore.Mvc.Utilities
@using OrchardCore.ContentManagement.Metadata.Models

@inject OrchardCore.ContentManagement.IContentManager ContentManager

@{
var name = (Model.PartFieldDefinition.PartDefinition.Name + "-" + Model.PartFieldDefinition.Name).HtmlClassify();
var contentItems = await ContentManager.GetAsync(Model.ContentItemIds);
var contentItems = await ContentManager.GetAsync(Model.ContentItemIds, VersionOptions.Published);
}

<div class="field field-type-contentpickerfield field-name-@name">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public async ValueTask<FluidValue> ProcessAsync(FluidValue input, FilterArgument
// List of content item ids
var contentItemIds = input.Enumerate(ctx).Select(x => x.ToStringValue()).ToArray();

return FluidValue.Create(await _contentManager.GetAsync(contentItemIds), ctx.Options);
return FluidValue.Create(await _contentManager.GetAsync(contentItemIds, VersionOptions.Published), ctx.Options);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static Task<ContentItem> GetContentItemByIdAsync(this IOrchardHelper orch
public static Task<IEnumerable<ContentItem>> GetContentItemsByIdAsync(this IOrchardHelper orchardHelper, IEnumerable<string> contentItemIds, bool latest = false)
{
var contentManager = orchardHelper.HttpContext.RequestServices.GetService<IContentManager>();
return contentManager.GetAsync(contentItemIds, latest);
return contentManager.GetAsync(contentItemIds, latest ? VersionOptions.Latest : VersionOptions.Published);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ await shellScope.UsingAsync(async scope =>
var allPublished = new Dictionary<string, ContentItem>();
var allLatest = new Dictionary<string, ContentItem>();

var allPublishedContentItems = await contentManager.GetAsync(updatedContentItemIds);
var allPublishedContentItems = await contentManager.GetAsync(updatedContentItemIds, VersionOptions.Published);
allPublished = allPublishedContentItems.DistinctBy(x => x.ContentItemId).ToDictionary(k => k.ContentItemId, v => v);
var allLatestContentItems = await contentManager.GetAsync(updatedContentItemIds, latest: true);
var allLatestContentItems = await contentManager.GetAsync(updatedContentItemIds, VersionOptions.Latest);
allLatest = allLatestContentItems.DistinctBy(x => x.ContentItemId).ToDictionary(k => k.ContentItemId, v => v);

// Group all DocumentIndex by index to batch update them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public override async Task<IDisplayResult> EditAsync(ContentOptionsViewModel mod
}

var results = new List<IDisplayResult>();
var taxonomies = await _contentManager.GetAsync(taxonomyContentItemIds);
var taxonomies = await _contentManager.GetAsync(taxonomyContentItemIds, VersionOptions.Published);

var position = 5;
foreach (var taxonomy in taxonomies)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using OrchardCore.ContentManagement.Handlers;

namespace OrchardCore.ContentManagement;

public static class ContentManagerExtensions
{
/// <summary>
/// Gets the published content item with the specified id.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="contentItemId">The content item id to load.</param>
public static Task<ContentItem> GetAsync(this IContentManager contentManager, string contentItemId)
=> contentManager.GetAsync(contentItemId, VersionOptions.Published);

/// <summary>
/// Creates (persists) a new Published content item.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="contentItem">The content instance filled with all necessary data.</param>
public static Task CreateAsync(this IContentManager contentManager, ContentItem contentItem)
{
return contentManager.CreateAsync(contentItem, VersionOptions.Published);
}

public static Task<TAspect> PopulateAspectAsync<TAspect>(this IContentManager contentManager, IContent content) where TAspect : new()
{
return contentManager.PopulateAspectAsync(content, new TAspect());
}

public static async Task<bool> HasPublishedVersionAsync(this IContentManager contentManager, IContent content)
{
if (content.ContentItem == null)
{
return false;
}

return content.ContentItem.IsPublished() || (await contentManager.GetAsync(content.ContentItem.ContentItemId, VersionOptions.Published) != null);
}

public static Task<ContentItemMetadata> GetContentItemMetadataAsync(this IContentManager contentManager, IContent content)
{
return contentManager.PopulateAspectAsync<ContentItemMetadata>(content);
}

public static async Task<IEnumerable<ContentItem>> LoadAsync(this IContentManager contentManager, IEnumerable<ContentItem> contentItems)
{
var results = new List<ContentItem>(contentItems.Count());

foreach (var contentItem in contentItems)
{
results.Add(await contentManager.LoadAsync(contentItem));
}

return results;
}

public static async IAsyncEnumerable<ContentItem> LoadAsync(this IContentManager contentManager, IAsyncEnumerable<ContentItem> contentItems)
{
await foreach (var contentItem in contentItems)
{
yield return await contentManager.LoadAsync(contentItem);
}
}

public static async Task<ContentValidateResult> UpdateValidateAndCreateAsync(this IContentManager contentManager, ContentItem contentItem, VersionOptions options)
{
await contentManager.UpdateAsync(contentItem);
var result = await contentManager.ValidateAsync(contentItem);

if (result.Succeeded)
{
await contentManager.CreateAsync(contentItem, options);
}

return result;
}

/// <summary>
/// Gets either the published container content item with the specified id, or if the json path supplied gets the contained content item.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="id">The content item id to load.</param>
/// <param name="jsonPath">The json path of the contained content item.</param>
public static Task<ContentItem> GetAsync(this IContentManager contentManager, string id, string jsonPath)
{
return contentManager.GetAsync(id, jsonPath, VersionOptions.Published);
}

/// <summary>
/// Gets either the container content item with the specified id and version, or if the json path supplied gets the contained content item.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="id">The id content item id to load.</param>
/// <param name="options">The version option.</param>
/// <param name="jsonPath">The json path of the contained content item.</param>
public static async Task<ContentItem> GetAsync(this IContentManager contentManager, string id, string jsonPath, VersionOptions options)
{
var contentItem = await contentManager.GetAsync(id, options);

// It represents a contained content item.
if (!string.IsNullOrEmpty(jsonPath))
{
var root = (JsonObject)contentItem.Content;
contentItem = root.SelectNode(jsonPath)?.ToObject<ContentItem>();

return contentItem;
}

return contentItem;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using OrchardCore.ContentManagement.Handlers;

Expand Down Expand Up @@ -34,7 +31,6 @@ public interface IContentManager
/// <param name="options">The version to create the item with.</param>
Task CreateAsync(ContentItem contentItem, VersionOptions options);


/// <summary>
/// Creates (puts) a new content item and manages removing and updating existing published or draft items.
/// </summary>
Expand Down Expand Up @@ -70,29 +66,12 @@ public interface IContentManager
/// <returns>The validation <see cref="ContentValidateResult"/> result.</returns>
Task<ContentValidateResult> RestoreAsync(ContentItem contentItem);

/// <summary>
/// Gets the published content item with the specified id.
/// </summary>
/// <param name="id">The content item id to load.</param>
Task<ContentItem> GetAsync(string id);

/// <summary>
/// Gets the content item with the specified id and version.
/// </summary>
/// <param name="id">The id content item id to load.</param>
/// <param name="contentItemId">The id of the content item to load.</param>
/// <param name="options">The version option.</param>
Task<ContentItem> GetAsync(string id, VersionOptions options);

/// <summary>
/// Gets the published content items with the specified ids.
/// </summary>
/// <param name="contentItemIds">The content item ids to load.</param>
/// <param name="latest">Whether a draft should be loaded if available. <c>false</c> by default.</param>
/// <remarks>
/// This method will always issue a database query.
/// This means that it should be used only to get a list of content items that have not been loaded.
/// </remarks>
Task<IEnumerable<ContentItem>> GetAsync(IEnumerable<string> contentItemIds, bool latest = false);
Task<ContentItem> GetAsync(string contentItemId, VersionOptions options);

/// <summary>
/// Gets the published content items with the specified ids.
Expand Down Expand Up @@ -138,7 +117,9 @@ public interface IContentManager
Task SaveDraftAsync(ContentItem contentItem);

Task PublishAsync(ContentItem contentItem);

Task UnpublishAsync(ContentItem contentItem);

Task<TAspect> PopulateAspectAsync<TAspect>(IContent content, TAspect aspect);

/// <summary>
Expand All @@ -148,138 +129,4 @@ public interface IContentManager
/// <returns>Clone of the item.</returns>
Task<ContentItem> CloneAsync(ContentItem contentItem);
}

public static class ContentManagerExtensions
{
/// <summary>
/// Creates (persists) a new Published content item.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="contentItem">The content instance filled with all necessary data.</param>
public static Task CreateAsync(this IContentManager contentManager, ContentItem contentItem)
{
return contentManager.CreateAsync(contentItem, VersionOptions.Published);
}

public static Task<TAspect> PopulateAspectAsync<TAspect>(this IContentManager contentManager, IContent content) where TAspect : new()
{
return contentManager.PopulateAspectAsync(content, new TAspect());
}

public static async Task<bool> HasPublishedVersionAsync(this IContentManager contentManager, IContent content)
{
if (content.ContentItem == null)
{
return false;
}

return content.ContentItem.IsPublished() || (await contentManager.GetAsync(content.ContentItem.ContentItemId, VersionOptions.Published) != null);
}

public static Task<ContentItemMetadata> GetContentItemMetadataAsync(this IContentManager contentManager, IContent content)
{
return contentManager.PopulateAspectAsync<ContentItemMetadata>(content);
}

public static async Task<IEnumerable<ContentItem>> LoadAsync(this IContentManager contentManager, IEnumerable<ContentItem> contentItems)
{
var results = new List<ContentItem>(contentItems.Count());

foreach (var contentItem in contentItems)
{
results.Add(await contentManager.LoadAsync(contentItem));
}

return results;
}

public static async IAsyncEnumerable<ContentItem> LoadAsync(this IContentManager contentManager, IAsyncEnumerable<ContentItem> contentItems)
{
await foreach (var contentItem in contentItems)
{
yield return await contentManager.LoadAsync(contentItem);
}
}

public static async Task<ContentValidateResult> UpdateValidateAndCreateAsync(this IContentManager contentManager, ContentItem contentItem, VersionOptions options)
{
await contentManager.UpdateAsync(contentItem);
var result = await contentManager.ValidateAsync(contentItem);

if (result.Succeeded)
{
await contentManager.CreateAsync(contentItem, options);
}

return result;
}

/// <summary>
/// Gets either the published container content item with the specified id, or if the json path supplied gets the contained content item.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="id">The content item id to load.</param>
/// <param name="jsonPath">The json path of the contained content item.</param>
public static Task<ContentItem> GetAsync(this IContentManager contentManager, string id, string jsonPath)
{
return contentManager.GetAsync(id, jsonPath, VersionOptions.Published);
}

/// <summary>
/// Gets either the container content item with the specified id and version, or if the json path supplied gets the contained content item.
/// </summary>
/// <param name="contentManager">The <see cref="IContentManager"/> instance.</param>
/// <param name="id">The id content item id to load.</param>
/// <param name="options">The version option.</param>
/// <param name="jsonPath">The json path of the contained content item.</param>
public static async Task<ContentItem> GetAsync(this IContentManager contentManager, string id, string jsonPath, VersionOptions options)
{
var contentItem = await contentManager.GetAsync(id, options);

// It represents a contained content item
if (!string.IsNullOrEmpty(jsonPath))
{
var root = (JsonObject)contentItem.Content;
contentItem = root.SelectNode(jsonPath)?.ToObject<ContentItem>();

return contentItem;
}

return contentItem;
}
}

public class VersionOptions
{
/// <summary>
/// Gets the latest version.
/// </summary>
public static VersionOptions Latest { get { return new VersionOptions { IsLatest = true }; } }

/// <summary>
/// Gets the latest published version.
/// </summary>
public static VersionOptions Published { get { return new VersionOptions { IsPublished = true }; } }

/// <summary>
/// Gets the latest draft version.
/// </summary>
public static VersionOptions Draft { get { return new VersionOptions { IsDraft = true }; } }

/// <summary>
/// Gets the latest version and creates a new version draft based on it.
/// </summary>
public static VersionOptions DraftRequired { get { return new VersionOptions { IsDraft = true, IsDraftRequired = true }; } }

/// <summary>
/// Gets all versions.
/// </summary>
public static VersionOptions AllVersions { get { return new VersionOptions { IsAllVersions = true }; } }

public bool IsLatest { get; private set; }
public bool IsPublished { get; private set; }
public bool IsDraft { get; private set; }
public bool IsDraftRequired { get; private set; }
public bool IsAllVersions { get; private set; }
}
}
Loading
Loading