-
-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathViewCountService.cs
More file actions
61 lines (46 loc) · 2.2 KB
/
ViewCountService.cs
File metadata and controls
61 lines (46 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using Microsoft.Extensions.Logging;
using OrchardCore.ContentManagement;
using OrchardCore.Modules;
using OrchardCoreContrib.Infrastructure;
using OrchardCoreContrib.ViewCount.Handlers;
using OrchardCoreContrib.ViewCount.Models;
namespace OrchardCoreContrib.ViewCount.Services;
/// <summary>
/// Provides functionality for tracking and updating view counts on content items.
/// </summary>
/// <remarks>The <see cref="ViewCountService"/> enables retrieval and incrementing of view counts for content
/// items. It coordinates with registered <see cref="IViewCountContentHandler"/> instances to allow custom logic to be
/// executed before and after a view is recorded. This service is typically used to monitor content popularity or
/// engagement.
/// </remarks>
public class ViewCountService(
IContentManager contentManager,
IEnumerable<IViewCountContentHandler> handlers,
ILogger<ViewCountService> logger) : IViewCountService
{
private static readonly SemaphoreSlim _semaphore = new(initialCount: 1, maxCount: 1);
/// <inheritdoc/>
public int GetViewsCount(ContentItem contentItem)
{
Guard.ArgumentNotNull(contentItem, nameof(contentItem));
var viewCountPart = contentItem.As<ViewCountPart>();
return viewCountPart?.Count ?? 0;
}
/// <inheritdoc/>
public async Task ViewAsync(ContentItem contentItem)
{
Guard.ArgumentNotNull(contentItem, nameof(contentItem));
await _semaphore.WaitAsync();
var viewCountPart = contentItem.As<ViewCountPart>()
?? throw new InvalidOperationException($"The content item doesn't have a `{nameof(ViewCountPart)}`.");
var count = viewCountPart.Count;
var context = new ViewCountContentContext(contentItem, count);
await handlers.InvokeAsync((handler, context) => handler.ViewingAsync(context), context, logger);
viewCountPart.Count = ++count;
contentItem.Content.ViewCountPart.Count = count;
await contentManager.UpdateAsync(contentItem);
context = new ViewCountContentContext(contentItem, count);
await handlers.InvokeAsync((handler, context) => handler.ViewedAsync(context), context, logger);
_semaphore.Release();
}
}