CarneiroTech/Services/CaseService.cs

137 lines
5.3 KiB
C#

using CarneiroTech.Models;
using Microsoft.Extensions.Caching.Memory;
using System.Globalization;
namespace CarneiroTech.Services;
public class CaseService : ICaseService
{
private readonly IMarkdownService _markdownService;
private readonly IMemoryCache _cache;
private readonly IWebHostEnvironment _environment;
private readonly string _casesPath;
private const string CACHE_KEY = "cases_retail";
private const int CACHE_MINUTES = 60;
public CaseService(IMarkdownService markdownService, IMemoryCache cache, IWebHostEnvironment environment)
{
_markdownService = markdownService;
_cache = cache;
_environment = environment;
_casesPath = Path.Combine(_environment.ContentRootPath, "Content", "Cases", "Retail");
}
public async Task<List<CaseModel>> GetAllCasesAsync()
{
if (_cache.TryGetValue(CACHE_KEY, out List<CaseModel>? cachedCases) && cachedCases != null)
{
return cachedCases;
}
var cases = new List<CaseModel>();
if (!Directory.Exists(_casesPath))
{
return cases;
}
var markdownFiles = Directory.GetFiles(_casesPath, "*.md");
foreach (var file in markdownFiles)
{
var caseModel = await ParseCaseFileAsync(file);
if (caseModel != null)
{
cases.Add(caseModel);
}
}
cases = cases.OrderBy(c => c.Metadata.Order)
.ThenByDescending(c => c.Metadata.Date)
.ToList();
_cache.Set(CACHE_KEY, cases, TimeSpan.FromMinutes(CACHE_MINUTES));
return cases;
}
public async Task<List<CaseModel>> GetFeaturedCasesAsync()
{
var allCases = await GetAllCasesAsync();
return allCases.Where(c => c.Metadata.Featured).ToList();
}
public async Task<CaseModel?> GetCaseBySlugAsync(string slug)
{
var allCases = await GetAllCasesAsync();
return allCases.FirstOrDefault(c => c.Metadata.Slug.Equals(slug, StringComparison.OrdinalIgnoreCase));
}
public async Task<List<string>> GetAllTagsAsync()
{
var allCases = await GetAllCasesAsync();
return allCases.SelectMany(c => c.Metadata.Tags).Distinct().OrderBy(t => t).ToList();
}
public async Task<List<CaseModel>> GetCasesByTagAsync(string tag)
{
var allCases = await GetAllCasesAsync();
return allCases.Where(c => c.Metadata.Tags.Contains(tag, StringComparer.OrdinalIgnoreCase)).ToList();
}
private async Task<CaseModel?> ParseCaseFileAsync(string filePath)
{
try
{
var content = await File.ReadAllTextAsync(filePath);
var frontMatter = _markdownService.ParseFrontMatter(content, out string bodyContent);
var metadata = new CaseMetadata
{
Title = GetStringValue(frontMatter, "title"),
Slug = GetStringValue(frontMatter, "slug"),
Summary = GetStringValue(frontMatter, "summary"),
Client = GetStringValue(frontMatter, "client"),
DeviceModel = GetStringValue(frontMatter, "device_model"),
EstimatedSavings = GetDecimalValue(frontMatter, "estimated_savings"),
Category = GetStringValue(frontMatter, "category"),
Thumbnail = GetStringValue(frontMatter, "thumbnail"),
Image = GetStringValue(frontMatter, "image"),
Tags = GetListValue(frontMatter, "tags"),
Featured = GetBoolValue(frontMatter, "featured"),
Order = GetIntValue(frontMatter, "order"),
Date = GetDateValue(frontMatter, "date"),
SeoTitle = GetStringValue(frontMatter, "seo_title"),
SeoDescription = GetStringValue(frontMatter, "seo_description"),
SeoKeywords = GetStringValue(frontMatter, "seo_keywords")
};
return new CaseModel
{
Metadata = metadata,
ContentHtml = _markdownService.ConvertToHtml(bodyContent),
ContentMarkdown = bodyContent
};
}
catch { return null; }
}
private string GetStringValue(Dictionary<string, object> dict, string key) =>
dict.ContainsKey(key) ? dict[key]?.ToString() ?? string.Empty : string.Empty;
private decimal GetDecimalValue(Dictionary<string, object> dict, string key) =>
dict.ContainsKey(key) && decimal.TryParse(dict[key]?.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out decimal res) ? res : 0;
private List<string> GetListValue(Dictionary<string, object> dict, string key) =>
dict.ContainsKey(key) && dict[key] is List<object> list ? list.Select(i => i?.ToString() ?? "").ToList() : new();
private bool GetBoolValue(Dictionary<string, object> dict, string key) =>
dict.ContainsKey(key) && (dict[key]?.ToString()?.ToLower() == "true" || dict[key]?.ToString() == "1");
private int GetIntValue(Dictionary<string, object> dict, string key) =>
dict.ContainsKey(key) && int.TryParse(dict[key]?.ToString(), out int res) ? res : 0;
private DateTime GetDateValue(Dictionary<string, object> dict, string key) =>
dict.ContainsKey(key) && DateTime.TryParse(dict[key]?.ToString(), CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime res) ? res : DateTime.MinValue;
}