using NPoco; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Infrastructure.Persistence.Dtos; using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; public class NotificationsRepository : INotificationsRepository { private readonly IScopeAccessor _scopeAccessor; public NotificationsRepository(IScopeAccessor scopeAccessor) => _scopeAccessor = scopeAccessor; private IScope? AmbientScope => _scopeAccessor.AmbientScope; public IEnumerable? GetUsersNotifications(IEnumerable userIds, string? action, IEnumerable nodeIds, Guid objectType) { var nodeIdsA = nodeIds.ToArray(); Sql? sql = AmbientScope?.SqlContext.Sql() .Select( "DISTINCT umbracoNode.id nodeId, umbracoUser.id userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action") .From() .InnerJoin().On(left => left.NodeId, right => right.NodeId) .InnerJoin().On(left => left.UserId, right => right.Id) .Where(x => x.NodeObjectType == objectType) .Where(x => x.Disabled == false) // only approved users .Where(x => x.Action == action); // on the specified action if (nodeIdsA.Length > 0) { sql? .WhereIn(x => x.NodeId, nodeIdsA); // for the specified nodes } sql? .OrderBy(x => x.Id) .OrderBy(dto => dto.NodeId); return AmbientScope?.Database.Fetch(sql) .Select(x => new Notification(x.NodeId, x.UserId, x.Action, objectType)); } public IEnumerable? GetUserNotifications(IUser user) { Sql? sql = AmbientScope?.SqlContext.Sql() .Select( "DISTINCT umbracoNode.id AS nodeId, umbracoUser2NodeNotify.userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action") .From() .InnerJoin() .On(dto => dto.NodeId, dto => dto.NodeId) .Where(dto => dto.UserId == user.Id) .OrderBy(dto => dto.NodeId); List? dtos = AmbientScope?.Database.Fetch(sql); // need to map the results return dtos?.Select(d => new Notification(d.NodeId, d.UserId, d.Action, d.NodeObjectType)).ToList(); } public IEnumerable SetNotifications(IUser user, IEntity entity, string[] actions) { DeleteNotifications(user, entity); return actions.Select(action => CreateNotification(user, entity, action)).ToList(); } public IEnumerable? GetEntityNotifications(IEntity entity) { Sql? sql = AmbientScope?.SqlContext.Sql() .Select( "DISTINCT umbracoNode.id as nodeId, umbracoUser2NodeNotify.userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action") .From() .InnerJoin() .On(dto => dto.NodeId, dto => dto.NodeId) .Where(dto => dto.NodeId == entity.Id) .OrderBy(dto => dto.NodeId); List? dtos = AmbientScope?.Database.Fetch(sql); // need to map the results return dtos?.Select(d => new Notification(d.NodeId, d.UserId, d.Action, d.NodeObjectType)).ToList(); } public int DeleteNotifications(IEntity entity) => AmbientScope?.Database.Delete("WHERE nodeId = @nodeId", new { nodeId = entity.Id }) ?? 0; public int DeleteNotifications(IUser user) => AmbientScope?.Database.Delete("WHERE userId = @userId", new { userId = user.Id }) ?? 0; public int DeleteNotifications(IUser user, IEntity entity) => // delete all settings on the node for this user AmbientScope?.Database.Delete( "WHERE userId = @userId AND nodeId = @nodeId", new { userId = user.Id, nodeId = entity.Id }) ?? 0; public Notification CreateNotification(IUser user, IEntity entity, string action) { Sql? sql = AmbientScope?.SqlContext.Sql() .Select("DISTINCT nodeObjectType") .From() .Where(nodeDto => nodeDto.NodeId == entity.Id); Guid? nodeType = AmbientScope?.Database.ExecuteScalar(sql); var dto = new User2NodeNotifyDto { Action = action, NodeId = entity.Id, UserId = user.Id }; AmbientScope?.Database.Insert(dto); return new Notification(dto.NodeId, dto.UserId, dto.Action, nodeType); } }