diff --git a/OrchardCore.slnx b/OrchardCore.slnx
index 6d7f2c617f1..e09406755dd 100644
--- a/OrchardCore.slnx
+++ b/OrchardCore.slnx
@@ -77,6 +77,7 @@
+
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/AdminMenu.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/AdminMenu.cs
new file mode 100644
index 00000000000..dafab7aab41
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/AdminMenu.cs
@@ -0,0 +1,52 @@
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.Localization;
+using OrchardCore.Contents.VersionPruning.Drivers;
+using OrchardCore.Navigation;
+
+namespace OrchardCore.Contents.VersionPruning;
+
+public sealed class AdminMenu : AdminNavigationProvider
+{
+ private static readonly RouteValueDictionary _routeValues = new()
+ {
+ { "area", "OrchardCore.Settings" },
+ { "groupId", ContentVersionPruningSettingsDisplayDriver.GroupId },
+ };
+
+ internal readonly IStringLocalizer S;
+
+ public AdminMenu(IStringLocalizer stringLocalizer)
+ {
+ S = stringLocalizer;
+ }
+
+ protected override ValueTask BuildAsync(NavigationBuilder builder)
+ {
+ if (NavigationHelper.UseLegacyFormat())
+ {
+ builder
+ .Add(S["Configuration"], configuration => configuration
+ .Add(S["Settings"], settings => settings
+ .Add(S["Content Version Pruning"], S["Content Version Pruning"], pruning => pruning
+ .Action("Index", "Admin", _routeValues)
+ .Permission(ContentVersionPruningPermissions.ManageContentVersionPruningSettings)
+ .LocalNav()
+ )
+ )
+ );
+
+ return ValueTask.CompletedTask;
+ }
+
+ builder
+ .Add(S["Settings"], settings => settings
+ .Add(S["Content Version Pruning"], S["Content Version Pruning"].PrefixPosition(), pruning => pruning
+ .Action("Index", "Admin", _routeValues)
+ .Permission(ContentVersionPruningPermissions.ManageContentVersionPruningSettings)
+ .LocalNav()
+ )
+ );
+
+ return ValueTask.CompletedTask;
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/ContentVersionPruningPermissions.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/ContentVersionPruningPermissions.cs
new file mode 100644
index 00000000000..b681e428707
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/ContentVersionPruningPermissions.cs
@@ -0,0 +1,10 @@
+using OrchardCore.Security.Permissions;
+
+namespace OrchardCore.Contents.VersionPruning;
+
+public static class ContentVersionPruningPermissions
+{
+ public static readonly Permission ManageContentVersionPruningSettings = new(
+ "ManageContentVersionPruningSettings",
+ "Manage Content Version Pruning settings");
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Controllers/AdminController.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Controllers/AdminController.cs
new file mode 100644
index 00000000000..a792f01200e
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Controllers/AdminController.cs
@@ -0,0 +1,68 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Localization;
+using OrchardCore.Contents.VersionPruning.Drivers;
+using OrchardCore.Contents.VersionPruning.Models;
+using OrchardCore.Contents.VersionPruning.Services;
+using OrchardCore.DisplayManagement.Notify;
+using OrchardCore.Entities;
+using OrchardCore.Modules;
+using OrchardCore.Settings;
+
+namespace OrchardCore.Contents.VersionPruning.Controllers;
+
+public sealed class AdminController : Controller
+{
+ private readonly IAuthorizationService _authorizationService;
+ private readonly IContentVersionPruningService _pruningService;
+ private readonly ISiteService _siteService;
+ private readonly IClock _clock;
+ private readonly INotifier _notifier;
+
+ internal readonly IHtmlLocalizer H;
+
+ public AdminController(
+ IAuthorizationService authorizationService,
+ IContentVersionPruningService pruningService,
+ ISiteService siteService,
+ IClock clock,
+ INotifier notifier,
+ IHtmlLocalizer htmlLocalizer)
+ {
+ _authorizationService = authorizationService;
+ _pruningService = pruningService;
+ _siteService = siteService;
+ _clock = clock;
+ _notifier = notifier;
+ H = htmlLocalizer;
+ }
+
+ [HttpPost]
+ public async Task Prune()
+ {
+ if (!await _authorizationService.AuthorizeAsync(User, ContentVersionPruningPermissions.ManageContentVersionPruningSettings))
+ {
+ return Forbid();
+ }
+
+ var settings = await _siteService.GetSettingsAsync();
+
+ var pruned = await _pruningService.PruneVersionsAsync(settings);
+
+ var container = await _siteService.LoadSiteSettingsAsync();
+ container.Alter(nameof(ContentVersionPruningSettings), settings =>
+ {
+ settings.LastRunUtc = _clock.UtcNow;
+ });
+
+ await _siteService.UpdateSiteSettingsAsync(container);
+
+ await _notifier.SuccessAsync(H["Content version pruning completed. {0} version(s) deleted.", pruned]);
+
+ return RedirectToAction("Index", "Admin", new
+ {
+ area = "OrchardCore.Settings",
+ groupId = ContentVersionPruningSettingsDisplayDriver.GroupId,
+ });
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Drivers/ContentVersionPruningSettingsDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Drivers/ContentVersionPruningSettingsDisplayDriver.cs
new file mode 100644
index 00000000000..fd1570813a6
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Drivers/ContentVersionPruningSettingsDisplayDriver.cs
@@ -0,0 +1,68 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using OrchardCore.Contents.VersionPruning.Models;
+using OrchardCore.Contents.VersionPruning.ViewModels;
+using OrchardCore.DisplayManagement.Entities;
+using OrchardCore.DisplayManagement.Handlers;
+using OrchardCore.DisplayManagement.Views;
+using OrchardCore.Settings;
+
+namespace OrchardCore.Contents.VersionPruning.Drivers;
+
+public sealed class ContentVersionPruningSettingsDisplayDriver : SiteDisplayDriver
+{
+ public const string GroupId = "ContentVersionPruningSettings";
+
+ private readonly IHttpContextAccessor _httpContextAccessor;
+ private readonly IAuthorizationService _authorizationService;
+
+ public ContentVersionPruningSettingsDisplayDriver(
+ IAuthorizationService authorizationService,
+ IHttpContextAccessor httpContextAccessor)
+ {
+ _authorizationService = authorizationService;
+ _httpContextAccessor = httpContextAccessor;
+ }
+
+ protected override string SettingsGroupId => GroupId;
+
+ public override async Task EditAsync(ISite site, ContentVersionPruningSettings settings, BuildEditorContext context)
+ {
+ if (!await _authorizationService.AuthorizeAsync(
+ _httpContextAccessor.HttpContext?.User,
+ ContentVersionPruningPermissions.ManageContentVersionPruningSettings))
+ {
+ return null;
+ }
+
+ return Initialize("ContentVersionPruningSettings_Edit", model =>
+ {
+ model.RetentionDays = settings.RetentionDays;
+ model.VersionsToKeep = settings.VersionsToKeep;
+ model.Disabled = settings.Disabled;
+ model.ContentTypes = settings.ContentTypes;
+ model.LastRunUtc = settings.LastRunUtc;
+ }).Location("Content:5")
+ .OnGroup(GroupId);
+ }
+
+ public override async Task UpdateAsync(ISite site, ContentVersionPruningSettings settings, UpdateEditorContext context)
+ {
+ if (!await _authorizationService.AuthorizeAsync(
+ _httpContextAccessor.HttpContext?.User,
+ ContentVersionPruningPermissions.ManageContentVersionPruningSettings))
+ {
+ return null;
+ }
+
+ var model = new ContentVersionPruningSettingsViewModel();
+ await context.Updater.TryUpdateModelAsync(model, Prefix);
+
+ settings.RetentionDays = model.RetentionDays;
+ settings.VersionsToKeep = model.VersionsToKeep;
+ settings.Disabled = model.Disabled;
+ settings.ContentTypes = model.ContentTypes ?? [];
+
+ return await EditAsync(site, settings, context);
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Manifest.cs
new file mode 100644
index 00000000000..65d559682f8
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Manifest.cs
@@ -0,0 +1,11 @@
+using OrchardCore.Modules.Manifest;
+
+[assembly: Module(
+ Name = "Content Version Pruning",
+ Author = ManifestConstants.OrchardCoreTeam,
+ Website = ManifestConstants.OrchardCoreWebsite,
+ Version = ManifestConstants.OrchardCoreVersion,
+ Description = "Provides a background task to prune old content item versions.",
+ Dependencies = ["OrchardCore.Contents"],
+ Category = "Content Management"
+)]
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Models/ContentVersionPruningSettings.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Models/ContentVersionPruningSettings.cs
new file mode 100644
index 00000000000..125df0b9934
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Models/ContentVersionPruningSettings.cs
@@ -0,0 +1,30 @@
+namespace OrchardCore.Contents.VersionPruning.Models;
+
+public class ContentVersionPruningSettings
+{
+ ///
+ /// The number of days after which non-latest, non-published content item versions are deleted.
+ ///
+ public int RetentionDays { get; set; } = 30;
+
+ ///
+ /// The number of the most-recent archived (non-latest, non-published) versions to retain
+ /// per content item, regardless of age.
+ ///
+ public int VersionsToKeep { get; set; } = 1;
+
+ ///
+ /// The content types to prune. When empty, all content types are pruned.
+ ///
+ public string[] ContentTypes { get; set; } = [];
+
+ ///
+ /// Whether the pruning background task is disabled.
+ ///
+ public bool Disabled { get; set; }
+
+ ///
+ /// The last time the pruning task was run.
+ ///
+ public DateTime? LastRunUtc { get; set; }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/OrchardCore.Contents.VersionPruning.csproj b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/OrchardCore.Contents.VersionPruning.csproj
new file mode 100644
index 00000000000..def469cdbd4
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/OrchardCore.Contents.VersionPruning.csproj
@@ -0,0 +1,27 @@
+
+
+
+ true
+
+ OrchardCore Contents Version Pruning
+ $(OCCMSDescription)
+
+ Provides a background task to prune old content item versions.
+ $(PackageTags) OrchardCoreCMS ContentManagement
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Permissions.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Permissions.cs
new file mode 100644
index 00000000000..1aec02a17b7
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Permissions.cs
@@ -0,0 +1,23 @@
+using OrchardCore.Security.Permissions;
+
+namespace OrchardCore.Contents.VersionPruning;
+
+public sealed class Permissions : IPermissionProvider
+{
+ private readonly IEnumerable _allPermissions =
+ [
+ ContentVersionPruningPermissions.ManageContentVersionPruningSettings,
+ ];
+
+ public Task> GetPermissionsAsync()
+ => Task.FromResult(_allPermissions);
+
+ public IEnumerable GetDefaultStereotypes() =>
+ [
+ new PermissionStereotype
+ {
+ Name = OrchardCoreConstants.Roles.Administrator,
+ Permissions = _allPermissions,
+ },
+ ];
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/ContentVersionPruningSelector.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/ContentVersionPruningSelector.cs
new file mode 100644
index 00000000000..4b09914b7ac
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/ContentVersionPruningSelector.cs
@@ -0,0 +1,28 @@
+using OrchardCore.ContentManagement;
+
+namespace OrchardCore.Contents.VersionPruning.Services;
+
+public static class ContentVersionPruningSelector
+{
+ public static List SelectForDeletion(IEnumerable candidates, int minVersionsToKeep)
+ {
+ var result = new List();
+
+ foreach (var group in candidates.GroupBy(x => x.ContentItemId))
+ {
+ // Sort newest-first so Skip() protects the most-recent N versions.
+ // Null ModifiedUtc is treated as oldest: Nullable.Compare places null before
+ // any non-null value, so descending order puts null-dated versions last.
+ var ordered = group
+ .Where(x =>
+ !x.Latest &&
+ !x.Published)
+ .OrderByDescending(x => x.ModifiedUtc, Comparer.Create(Nullable.Compare))
+ .Skip(minVersionsToKeep);
+
+ result.AddRange(ordered);
+ }
+
+ return result;
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/ContentVersionPruningService.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/ContentVersionPruningService.cs
new file mode 100644
index 00000000000..1ffa1703a55
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/ContentVersionPruningService.cs
@@ -0,0 +1,77 @@
+using Microsoft.Extensions.Logging;
+using OrchardCore.ContentManagement;
+using OrchardCore.ContentManagement.Records;
+using OrchardCore.Contents.VersionPruning.Models;
+using OrchardCore.Modules;
+using YesSql;
+using YesSql.Services;
+
+namespace OrchardCore.Contents.VersionPruning.Services;
+
+public class ContentVersionPruningService : IContentVersionPruningService
+{
+ private readonly ISession _session;
+ private readonly IClock _clock;
+ private readonly ILogger _logger;
+
+ public ContentVersionPruningService(
+ ISession session,
+ IClock clock,
+ ILogger logger)
+ {
+ _session = session;
+ _clock = clock;
+ _logger = logger;
+ }
+
+ public async Task PruneVersionsAsync(ContentVersionPruningSettings settings)
+ {
+ var candidates = await GetDeletionCandidatesAsync(settings);
+
+ var deleted = 0;
+ foreach (var version in candidates)
+ {
+ try
+ {
+ _session.Delete(version);
+ deleted++;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to prune content item {ContentItemId} version {ContentItemVersionId}", version.ContentItemId, version.ContentItemVersionId);
+ }
+ }
+
+ if (candidates.Count != deleted && _logger.IsEnabled(LogLevel.Debug))
+ {
+ _logger.LogDebug("Content version pruning count doesn't match - expected to delete {ToDeleteCount}, actually deleted only {Deleted}", candidates.Count, deleted);
+ }
+
+ return deleted;
+ }
+
+ private async Task> GetDeletionCandidatesAsync(ContentVersionPruningSettings settings)
+ {
+ // Fetch all candidate archived versions (neither latest nor published)
+ // that are older than the retention threshold. Versions with a null ModifiedUtc
+ // are treated as oldest (they predate any known modification) and are always included.
+ var dateThreshold = _clock.UtcNow.AddDays(-settings.RetentionDays);
+ var query = _session
+ .Query(x =>
+ !x.Latest &&
+ !x.Published &&
+ (x.ModifiedUtc == null || x.ModifiedUtc < dateThreshold));
+
+ var filterByType = settings.ContentTypes?.Length > 0;
+ if (filterByType)
+ {
+ query = query.Where(x => x.ContentType.IsIn(settings.ContentTypes));
+ }
+
+ var candidates = await query.ListAsync();
+
+ var versionsToKeep = Math.Max(0, settings.VersionsToKeep);
+
+ return ContentVersionPruningSelector.SelectForDeletion(candidates, versionsToKeep);
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/IContentVersionPruningService.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/IContentVersionPruningService.cs
new file mode 100644
index 00000000000..de6bf0e3ed2
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Services/IContentVersionPruningService.cs
@@ -0,0 +1,15 @@
+using OrchardCore.Contents.VersionPruning.Models;
+
+namespace OrchardCore.Contents.VersionPruning.Services;
+
+public interface IContentVersionPruningService
+{
+ ///
+ /// Deletes old content item versions that are neither the latest nor published,
+ /// and whose ModifiedUtc is older than the retention period defined in
+ /// , while honouring .
+ ///
+ /// The pruning settings to apply.
+ /// The number of versions deleted.
+ Task PruneVersionsAsync(ContentVersionPruningSettings settings);
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Startup.cs
new file mode 100644
index 00000000000..ea1f818368a
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Startup.cs
@@ -0,0 +1,39 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using OrchardCore.BackgroundTasks;
+using OrchardCore.Contents.VersionPruning.Controllers;
+using OrchardCore.Contents.VersionPruning.Drivers;
+using OrchardCore.Contents.VersionPruning.Services;
+using OrchardCore.Contents.VersionPruning.Tasks;
+using OrchardCore.DisplayManagement.Handlers;
+using OrchardCore.Modules;
+using OrchardCore.Mvc.Core.Utilities;
+using OrchardCore.Navigation;
+using OrchardCore.Security.Permissions;
+
+namespace OrchardCore.Contents.VersionPruning;
+
+public sealed class Startup : StartupBase
+{
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ services.AddScoped();
+ services.AddSingleton();
+ services.AddSiteDisplayDriver();
+ services.AddNavigationProvider();
+ services.AddPermissionProvider();
+ }
+
+ public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
+ {
+ var controllerName = typeof(AdminController).ControllerName();
+
+ routes.MapAreaControllerRoute(
+ name: "ContentsVersionPruningPrune",
+ areaName: "OrchardCore.Contents.VersionPruning",
+ pattern: "Contents/VersionPruning/Prune",
+ defaults: new { controller = controllerName, action = nameof(AdminController.Prune) }
+ );
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Tasks/ContentVersionPruningBackgroundTask.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Tasks/ContentVersionPruningBackgroundTask.cs
new file mode 100644
index 00000000000..864c4eefb26
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Tasks/ContentVersionPruningBackgroundTask.cs
@@ -0,0 +1,60 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using OrchardCore.BackgroundTasks;
+using OrchardCore.Contents.VersionPruning.Models;
+using OrchardCore.Contents.VersionPruning.Services;
+using OrchardCore.Entities;
+using OrchardCore.Modules;
+using OrchardCore.Settings;
+
+namespace OrchardCore.Contents.VersionPruning.Tasks;
+
+[BackgroundTask(
+ Schedule = "0 0 * * *",
+ Title = "Content Version Pruning Background Task",
+ Description = "Regularly deletes old non-latest, non-published content item versions.",
+ Enable = false,
+ LockTimeout = 3_000,
+ LockExpiration = 30_000)]
+public sealed class ContentVersionPruningBackgroundTask : IBackgroundTask
+{
+ public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken)
+ {
+ var siteService = serviceProvider.GetRequiredService();
+
+ var settings = await siteService.GetSettingsAsync();
+ if (settings.Disabled)
+ {
+ return;
+ }
+
+ var logger = serviceProvider.GetRequiredService>();
+
+ try
+ {
+ var clock = serviceProvider.GetRequiredService();
+ var pruningService = serviceProvider.GetRequiredService();
+
+ logger.LogDebug("Starting content version pruning.");
+
+ var pruned = await pruningService.PruneVersionsAsync(settings);
+
+ if (logger.IsEnabled(LogLevel.Debug))
+ {
+ logger.LogDebug("Content version pruning completed. {PrunedCount} versions were deleted.", pruned);
+ }
+
+ var container = await siteService.LoadSiteSettingsAsync();
+ container.Alter(nameof(ContentVersionPruningSettings), settings =>
+ {
+ settings.LastRunUtc = clock.UtcNow;
+ });
+
+ await siteService.UpdateSiteSettingsAsync(container);
+ }
+ catch (Exception ex) when (!ex.IsFatal())
+ {
+ logger.LogError(ex, "Error while pruning content item versions.");
+ }
+ }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/ViewModels/ContentVersionPruningSettingsViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/ViewModels/ContentVersionPruningSettingsViewModel.cs
new file mode 100644
index 00000000000..bb5a9d2811e
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/ViewModels/ContentVersionPruningSettingsViewModel.cs
@@ -0,0 +1,11 @@
+namespace OrchardCore.Contents.VersionPruning.ViewModels;
+
+public class ContentVersionPruningSettingsViewModel
+{
+ public int RetentionDays { get; set; }
+ public int VersionsToKeep { get; set; }
+ public string[] ContentTypes { get; set; } = [];
+
+ public bool Disabled { get; set; }
+ public DateTime? LastRunUtc { get; set; }
+}
diff --git a/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Views/ContentVersionPruningSettings_Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Views/ContentVersionPruningSettings_Edit.cshtml
new file mode 100644
index 00000000000..826a8fe41cb
--- /dev/null
+++ b/src/OrchardCore.Modules/OrchardCore.Contents.VersionPruning/Views/ContentVersionPruningSettings_Edit.cshtml
@@ -0,0 +1,48 @@
+@model ContentVersionPruningSettingsViewModel
+
+
+
+
+
+ @T["Whether the pruning task is disabled."]
+
+
+
+
+
+
+ @T["Non-latest, non-published versions older than this number of days will be deleted."]
+
+
+
+
+
+ @T["The number of most-recent archived (non-latest, non-published) versions to always retain per content item, regardless of age. Set to 0 to disable this protection."]
+
+
+
+
+ @T["Select the content types whose old archived versions should be pruned. Leave all unchecked to prune all content types."]
+ @await Component.InvokeAsync("SelectContentTypes", new { selectedContentTypes = Model.ContentTypes, htmlName = Html.NameFor(m => m.ContentTypes) })
+