< Summary

Information
Class: Chronicis.Api.Services.WorldLinkService
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Services/WorldLinkService.cs
Line coverage
100%
Covered lines: 2
Uncovered lines: 0
Coverable lines: 2
Total lines: 142
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Api/Services/WorldLinkService.cs

#LineLine coverage
 1using Chronicis.Api.Data;
 2using Chronicis.Api.Models;
 3using Chronicis.Shared.DTOs;
 4using Chronicis.Shared.Models;
 5using Microsoft.EntityFrameworkCore;
 6
 7namespace Chronicis.Api.Services;
 8
 9public sealed class WorldLinkService : IWorldLinkService
 10{
 11    private readonly ChronicisDbContext _context;
 12
 13    public WorldLinkService(ChronicisDbContext context)
 14    {
 415        _context = context;
 416    }
 17
 18    public async Task<ServiceResult<List<WorldLinkDto>>> GetWorldLinksAsync(Guid worldId, Guid userId)
 19    {
 20        var world = await _context.Worlds
 21            .AsNoTracking()
 22            .FirstOrDefaultAsync(w => w.Id == worldId && w.OwnerId == userId);
 23
 24        if (world == null)
 25        {
 26            return ServiceResult<List<WorldLinkDto>>.NotFound("World not found or access denied");
 27        }
 28
 29        var links = await _context.WorldLinks
 30            .AsNoTracking()
 31            .Where(wl => wl.WorldId == worldId)
 32            .OrderBy(wl => wl.Title)
 33            .Select(wl => new WorldLinkDto
 34            {
 35                Id = wl.Id,
 36                WorldId = wl.WorldId,
 37                Url = wl.Url,
 38                Title = wl.Title,
 39                Description = wl.Description,
 40                CreatedAt = wl.CreatedAt
 41            })
 42            .ToListAsync();
 43
 44        return ServiceResult<List<WorldLinkDto>>.Success(links);
 45    }
 46
 47    public async Task<ServiceResult<WorldLinkDto>> CreateWorldLinkAsync(Guid worldId, WorldLinkCreateDto dto, Guid userI
 48    {
 49        var world = await _context.Worlds
 50            .FirstOrDefaultAsync(w => w.Id == worldId && w.OwnerId == userId);
 51
 52        if (world == null)
 53        {
 54            return ServiceResult<WorldLinkDto>.NotFound("World not found or access denied");
 55        }
 56
 57        var link = new WorldLink
 58        {
 59            Id = Guid.NewGuid(),
 60            WorldId = worldId,
 61            Url = dto.Url.Trim(),
 62            Title = dto.Title.Trim(),
 63            Description = string.IsNullOrWhiteSpace(dto.Description) ? null : dto.Description.Trim(),
 64            CreatedAt = DateTime.UtcNow
 65        };
 66
 67        _context.WorldLinks.Add(link);
 68        await _context.SaveChangesAsync();
 69
 70        return ServiceResult<WorldLinkDto>.Success(new WorldLinkDto
 71        {
 72            Id = link.Id,
 73            WorldId = link.WorldId,
 74            Url = link.Url,
 75            Title = link.Title,
 76            Description = link.Description,
 77            CreatedAt = link.CreatedAt
 78        });
 79    }
 80
 81    public async Task<ServiceResult<WorldLinkDto>> UpdateWorldLinkAsync(Guid worldId, Guid linkId, WorldLinkUpdateDto dt
 82    {
 83        var world = await _context.Worlds
 84            .AsNoTracking()
 85            .FirstOrDefaultAsync(w => w.Id == worldId && w.OwnerId == userId);
 86
 87        if (world == null)
 88        {
 89            return ServiceResult<WorldLinkDto>.NotFound("World not found or access denied");
 90        }
 91
 92        var link = await _context.WorldLinks
 93            .FirstOrDefaultAsync(wl => wl.Id == linkId && wl.WorldId == worldId);
 94
 95        if (link == null)
 96        {
 97            return ServiceResult<WorldLinkDto>.NotFound("Link not found");
 98        }
 99
 100        link.Url = dto.Url.Trim();
 101        link.Title = dto.Title.Trim();
 102        link.Description = string.IsNullOrWhiteSpace(dto.Description) ? null : dto.Description.Trim();
 103
 104        await _context.SaveChangesAsync();
 105
 106        return ServiceResult<WorldLinkDto>.Success(new WorldLinkDto
 107        {
 108            Id = link.Id,
 109            WorldId = link.WorldId,
 110            Url = link.Url,
 111            Title = link.Title,
 112            Description = link.Description,
 113            CreatedAt = link.CreatedAt
 114        });
 115    }
 116
 117    public async Task<ServiceResult<bool>> DeleteWorldLinkAsync(Guid worldId, Guid linkId, Guid userId)
 118    {
 119        var world = await _context.Worlds
 120            .AsNoTracking()
 121            .FirstOrDefaultAsync(w => w.Id == worldId && w.OwnerId == userId);
 122
 123        if (world == null)
 124        {
 125            return ServiceResult<bool>.NotFound("World not found or access denied");
 126        }
 127
 128        var link = await _context.WorldLinks
 129            .FirstOrDefaultAsync(wl => wl.Id == linkId && wl.WorldId == worldId);
 130
 131        if (link == null)
 132        {
 133            return ServiceResult<bool>.NotFound("Link not found");
 134        }
 135
 136        _context.WorldLinks.Remove(link);
 137        await _context.SaveChangesAsync();
 138
 139        return ServiceResult<bool>.Success(true);
 140    }
 141}
 142