Initial commit

This commit is contained in:
2026-06-02 10:51:14 +02:00
committed by kawa
commit d19092c84e
182 changed files with 13757 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
using Microsoft.SharePoint.Client;
using Serilog;
using SharepointToolbox.Web.Core.Helpers;
using SharepointToolbox.Web.Core.Models;
using SharepointToolbox.Web.Services.Audit;
namespace SharepointToolbox.Web.Services;
public class FolderStructureService : IFolderStructureService
{
private readonly IAuditService _audit;
public FolderStructureService(IAuditService audit) { _audit = audit; }
public async Task<BulkOperationSummary<string>> CreateFoldersAsync(
ClientContext ctx, string libraryTitle,
IReadOnlyList<FolderStructureRow> rows,
IProgress<OperationProgress> progress, CancellationToken ct)
{
var list = ctx.Web.Lists.GetByTitle(libraryTitle);
ctx.Load(list, l => l.RootFolder.ServerRelativeUrl);
await ExecuteQueryRetryHelper.ExecuteQueryRetryAsync(ctx, progress, ct);
var baseUrl = list.RootFolder.ServerRelativeUrl.TrimEnd('/');
var folderPaths = BuildUniquePaths(rows);
var result = await BulkOperationRunner.RunAsync(
folderPaths,
async (path, idx, token) =>
{
ctx.Web.Folders.Add($"{baseUrl}/{path}");
await ExecuteQueryRetryHelper.ExecuteQueryRetryAsync(ctx, progress, token);
Log.Information("Created folder: {Path}", $"{baseUrl}/{path}");
},
progress, ct);
await _audit.LogAsync("CreateFolderStructure", ctx.Url, new[] { ctx.Url },
$"{result.SuccessCount} folders created in '{libraryTitle}', {(result.TotalCount - result.SuccessCount)} failed");
return result;
}
internal static IReadOnlyList<string> BuildUniquePaths(IReadOnlyList<FolderStructureRow> rows)
{
var paths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var row in rows)
{
var parts = new[] { row.Level1, row.Level2, row.Level3, row.Level4 }
.Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
var current = string.Empty;
foreach (var part in parts)
{
current = string.IsNullOrEmpty(current) ? part.Trim() : $"{current}/{part.Trim()}";
paths.Add(current);
}
}
return paths.OrderBy(p => p.Count(c => c == '/')).ThenBy(p => p, StringComparer.OrdinalIgnoreCase).ToList();
}
}