1184 lines
40 KiB
C#
1184 lines
40 KiB
C#
using DuoVia.FuzzyStrings;
|
|
using NTDLS.SqliteDapperWrapper;
|
|
using ZelWiki.Caching;
|
|
using ZelWiki.Engine.Library;
|
|
using ZelWiki.Library;
|
|
using ZelWiki.Models.DataModels;
|
|
|
|
namespace ZelWiki.Repository
|
|
{
|
|
public static class PageRepository
|
|
{
|
|
public static Page? GetPageRevisionInfoById(int pageId, int? revision = null)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.QuerySingleOrDefault<Page>("GetPageRevisionInfoById.sql", param);
|
|
}
|
|
|
|
public static ProcessingInstructionCollection GetPageProcessingInstructionsByPageId(int pageId,
|
|
bool allowCache = true)
|
|
{
|
|
if (allowCache)
|
|
{
|
|
var cacheKey = WikiCacheKeyFunction.Build(WikiCache.Category.Page, [pageId]);
|
|
if (!WikiCache.TryGet<ProcessingInstructionCollection>(cacheKey, out var result))
|
|
{
|
|
result = GetPageProcessingInstructionsByPageId(pageId, false);
|
|
WikiCache.Put(cacheKey, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return new ProcessingInstructionCollection()
|
|
{
|
|
Collection = ManagedDataStorage.Pages
|
|
.Query<ProcessingInstruction>("GetPageProcessingInstructionsByPageId.sql", param).ToList()
|
|
};
|
|
}
|
|
|
|
public static List<PageTag> GetPageTagsById(int pageId, bool allowCache = true)
|
|
{
|
|
if (allowCache)
|
|
{
|
|
var cacheKey = WikiCacheKeyFunction.Build(WikiCache.Category.Page, [pageId]);
|
|
if (!WikiCache.TryGet<List<PageTag>>(cacheKey, out var result))
|
|
{
|
|
result = GetPageTagsById(pageId, false);
|
|
WikiCache.Put(cacheKey, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Query<PageTag>("GetPageTagsById.sql", param).ToList();
|
|
}
|
|
|
|
public static List<PageRevision> GetPageRevisionsInfoByNavigationPaged(
|
|
string navigation, int pageNumber, string? orderBy = null, string? orderByDirection = null,
|
|
int? pageSize = null)
|
|
{
|
|
pageSize ??= ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
Navigation = navigation,
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetPageRevisionsInfoByNavigationPaged.sql", orderBy,
|
|
orderByDirection);
|
|
return o.Query<PageRevision>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<PageRevision> GetTopRecentlyModifiedPagesInfoByUserId(Guid userId, int topCount)
|
|
{
|
|
var param = new
|
|
{
|
|
UserId = userId,
|
|
TopCount = topCount
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Query<PageRevision>("GetTopRecentlyModifiedPagesInfoByUserId.sql", param)
|
|
.ToList();
|
|
}
|
|
|
|
public static string? GetPageNavigationByPageId(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.ExecuteScalar<string>("GetPageNavigationByPageId.sql", param);
|
|
}
|
|
|
|
public static List<Page> GetTopRecentlyModifiedPagesInfo(int topCount)
|
|
{
|
|
var param = new
|
|
{
|
|
TopCount = topCount
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Query<Page>("GetTopRecentlyModifiedPagesInfo.sql", param).ToList();
|
|
}
|
|
|
|
private static List<PageSearchToken> GetFuzzyPageSearchTokens(List<PageToken> tokens, double minimumMatchScore)
|
|
{
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
MinimumMatchScore = minimumMatchScore,
|
|
TokenCount = tokens.Count
|
|
};
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempSearchTerms", tokens.Distinct());
|
|
return o.Query<PageSearchToken>("GetFuzzyPageSearchTokens.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
private static List<PageSearchToken> GetExactPageSearchTokens(List<PageToken> tokens, double minimumMatchScore)
|
|
{
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
MinimumMatchScore = minimumMatchScore,
|
|
TokenCount = tokens.Count
|
|
};
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempSearchTerms", tokens.Distinct());
|
|
return o.Query<PageSearchToken>("GetExactPageSearchTokens.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
private static List<PageSearchToken> GetMeteredPageSearchTokens(List<string> searchTerms,
|
|
bool allowFuzzyMatching, bool allowCache = true)
|
|
{
|
|
if (allowCache)
|
|
{
|
|
var cacheKey = WikiCacheKeyFunction.Build(WikiCache.Category.Search,
|
|
[string.Join(',', searchTerms), allowFuzzyMatching]);
|
|
if (!WikiCache.TryGet<List<PageSearchToken>>(cacheKey, out var result))
|
|
{
|
|
result = GetMeteredPageSearchTokens(searchTerms, allowFuzzyMatching, false);
|
|
WikiCache.Put(cacheKey, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
var minimumMatchScore = ConfigurationRepository.Get<float>("Search", "Minimum Match Score");
|
|
|
|
var searchTokens = (from o in searchTerms
|
|
select new PageToken
|
|
{
|
|
Token = o,
|
|
DoubleMetaphone = o.ToDoubleMetaphone()
|
|
}).ToList();
|
|
|
|
if (allowFuzzyMatching == true)
|
|
{
|
|
var allTokens = GetExactPageSearchTokens(searchTokens, minimumMatchScore / 2.0);
|
|
var fuzzyTokens = GetFuzzyPageSearchTokens(searchTokens, minimumMatchScore / 2.0);
|
|
|
|
allTokens.AddRange(fuzzyTokens);
|
|
|
|
return allTokens
|
|
.GroupBy(token => token.PageId)
|
|
.Where(group => group.Sum(g => g.Score) >= minimumMatchScore)
|
|
.Select(group => new PageSearchToken
|
|
{
|
|
PageId = group.Key,
|
|
Match = group.Max(g => g.Match),
|
|
Weight = group.Max(g => g.Weight),
|
|
Score = group.Max(g => g.Score)
|
|
}).ToList();
|
|
}
|
|
else
|
|
{
|
|
return GetExactPageSearchTokens(searchTokens, minimumMatchScore / 2.0);
|
|
}
|
|
}
|
|
|
|
public static List<Page> PageSearch(List<string> searchTerms)
|
|
{
|
|
if (searchTerms.Count == 0)
|
|
{
|
|
return new List<Page>();
|
|
}
|
|
|
|
var allowFuzzyMatching = ConfigurationRepository.Get<bool>("Search", "Allow Fuzzy Matching");
|
|
var meteredSearchTokens = GetMeteredPageSearchTokens(searchTerms, allowFuzzyMatching == true);
|
|
if (meteredSearchTokens.Count == 0)
|
|
{
|
|
return new List<Page>();
|
|
}
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
MaximumScore = meteredSearchTokens.Max(t => t.Score)
|
|
};
|
|
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
using var tempTable = o.CreateTempTableFrom("TempSearchTerms", meteredSearchTokens);
|
|
return o.Query<Page>("PageSearch.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<Page> PageSearchPaged(List<string> searchTerms, int pageNumber, int? pageSize = null,
|
|
bool? allowFuzzyMatching = null)
|
|
{
|
|
if (searchTerms.Count == 0)
|
|
{
|
|
return new List<Page>();
|
|
}
|
|
|
|
pageSize ??= ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
allowFuzzyMatching ??= ConfigurationRepository.Get<bool>("Search", "Allow Fuzzy Matching");
|
|
|
|
var meteredSearchTokens = GetMeteredPageSearchTokens(searchTerms, allowFuzzyMatching == true);
|
|
if (meteredSearchTokens.Count == 0)
|
|
{
|
|
return new List<Page>();
|
|
}
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize,
|
|
MaximumScore = meteredSearchTokens.Max(t => t.Score)
|
|
};
|
|
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
using var tempTable = o.CreateTempTableFrom("TempSearchTerms", meteredSearchTokens);
|
|
var results = o.Query<Page>("PageSearchPaged.sql", param).ToList();
|
|
return results;
|
|
});
|
|
}
|
|
|
|
public static List<RelatedPage> GetSimilarPagesPaged(int pageId, int similarity, int pageNumber,
|
|
int? pageSize = null)
|
|
{
|
|
pageSize ??= ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Similarity = similarity,
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Query<RelatedPage>("GetSimilarPagesPaged.sql", param).ToList();
|
|
}
|
|
|
|
public static List<RelatedPage> GetRelatedPagesPaged(int pageId, int pageNumber, int? pageSize = null)
|
|
{
|
|
pageSize ??= ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Query<RelatedPage>("GetRelatedPagesPaged.sql", param).ToList();
|
|
}
|
|
|
|
public static void FlushPageCache(int pageId)
|
|
{
|
|
var pageNavigation = GetPageNavigationByPageId(pageId);
|
|
WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.Page, [pageNavigation]));
|
|
WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.Page, [pageId]));
|
|
}
|
|
|
|
public static void InsertPageComment(int pageId, Guid userId, string body)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
UserId = userId,
|
|
Body = body,
|
|
CreatedDate = DateTime.UtcNow
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Execute("InsertPageComment.sql", param);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void DeletePageCommentById(int pageId, int commentId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
CommentId = commentId
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Execute("DeletePageCommentById.sql", param);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void DeletePageCommentByUserAndId(int pageId, Guid userId, int commentId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
UserId = userId,
|
|
CommentId = commentId
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Execute("DeletePageCommentByUserAndId.sql", param);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static List<PageComment> GetPageCommentsPaged(string navigation, int pageNumber, bool allowCache = true)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
if (allowCache)
|
|
{
|
|
var cacheKey = WikiCacheKeyFunction.Build(WikiCache.Category.Page, [navigation, pageNumber, pageSize]);
|
|
if (!WikiCache.TryGet<List<PageComment>>(cacheKey, out var result))
|
|
{
|
|
result = GetPageCommentsPaged(navigation, pageNumber, false);
|
|
WikiCache.Put(cacheKey, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
var param = new
|
|
{
|
|
Navigation = navigation,
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.Query<PageComment>("GetPageCommentsPaged.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<NonexistentPage> GetMissingPagesPaged(int pageNumber, string? orderBy = null,
|
|
string? orderByDirection = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetMissingPagesPaged.sql", orderBy, orderByDirection);
|
|
return ManagedDataStorage.Pages.Query<NonexistentPage>(query, param).ToList();
|
|
}
|
|
|
|
public static void UpdateSinglePageReference(string pageNavigation, int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
@PageId = pageId,
|
|
@PageNavigation = pageNavigation
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Execute("UpdateSinglePageReference.sql", param);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void UpdatePageReferences(int pageId, List<PageReference> referencesPageNavigations)
|
|
{
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempReferences", referencesPageNavigations.Distinct());
|
|
return o.Query<Page>("UpdatePageReferences.sql", param).ToList();
|
|
});
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static List<Page> GetAllPagesByInstructionPaged(int pageNumber, string? instruction = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize,
|
|
Instruction = instruction
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.Query<Page>("GetAllPagesByInstructionPaged.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<int> GetDeletedPageIdsByTokens(List<string>? tokens)
|
|
{
|
|
if (tokens == null || tokens.Count == 0)
|
|
{
|
|
return new List<int>();
|
|
}
|
|
|
|
return ManagedDataStorage.DeletedPages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
TokenCount = tokens.Count
|
|
};
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempTokens", tokens);
|
|
return o.Query<int>("GetDeletedPageIdsByTokens.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<int> GetPageIdsByTokens(List<string>? tokens)
|
|
{
|
|
if (tokens == null || tokens.Count == 0)
|
|
{
|
|
return new List<int>();
|
|
}
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
TokenCount = tokens.Count
|
|
};
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempTokens", tokens);
|
|
return o.Query<int>("GetPageIdsByTokens.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<Page> GetAllNamespacePagesPaged(int pageNumber, string namespaceName,
|
|
string? orderBy = null, string? orderByDirection = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize,
|
|
Namespace = namespaceName
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
var query = RepositoryHelper.TransposeOrderby("GetAllNamespacePagesPaged.sql", orderBy,
|
|
orderByDirection);
|
|
return o.Query<Page>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="pageNumber"></param>
|
|
/// <param name="orderBy"></param>
|
|
/// <param name="orderByDirection"></param>
|
|
/// <param name="searchTerms"></param>
|
|
/// <returns></returns>
|
|
public static List<Page> GetAllPagesPaged(int pageNumber,
|
|
string? orderBy = null, string? orderByDirection = null, List<string>? searchTerms = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
if (searchTerms?.Count > 0)
|
|
{
|
|
var pageIds = GetPageIdsByTokens(searchTerms);
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
using var deletedpagerevisions_db = o.Attach("deletedpagerevisions.db", "deletedpagerevisions_db");
|
|
using var tempTable = o.CreateTempTableFrom("TempPageIds", pageIds);
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetAllPagesByPageIdPaged.sql", orderBy,
|
|
orderByDirection);
|
|
return o.Query<Page>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
using var deletedpagerevisions_db = o.Attach("deletedpagerevisions.db", "deletedpagerevisions_db");
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetAllPagesPaged.sql", orderBy, orderByDirection);
|
|
return o.Query<Page>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="pageNumber"></param>
|
|
/// <param name="orderBy"></param>
|
|
/// <param name="orderByDirection"></param>
|
|
/// <param name="searchTerms"></param>
|
|
/// <returns></returns>
|
|
public static List<Page> GetAllDeletedPagesPaged(int pageNumber, string? orderBy = null,
|
|
string? orderByDirection = null, List<string>? searchTerms = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
if (searchTerms?.Count > 0)
|
|
{
|
|
var pageIds = GetDeletedPageIdsByTokens(searchTerms);
|
|
return ManagedDataStorage.DeletedPages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
using var tempTable = o.CreateTempTableFrom("TempPageIds", pageIds);
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetAllDeletedPagesByPageIdPaged.sql", orderBy,
|
|
orderByDirection);
|
|
return o.Query<Page>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
return ManagedDataStorage.DeletedPages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
var query = RepositoryHelper.TransposeOrderby("GetAllDeletedPagesPaged.sql", orderBy, orderByDirection);
|
|
return o.Query<Page>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
public static List<NamespaceStat> GetAllNamespacesPaged(int pageNumber, string? orderBy = null,
|
|
string? orderByDirection = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetAllNamespacesPaged.sql", orderBy, orderByDirection);
|
|
|
|
return ManagedDataStorage.Pages.Query<NamespaceStat>(query, param).ToList();
|
|
}
|
|
|
|
public static List<string> GetAllNamespaces()
|
|
=> ManagedDataStorage.Pages.Query<string>("GetAllNamespaces.sql").ToList();
|
|
|
|
public static List<Page> GetAllPages()
|
|
=> ManagedDataStorage.Pages.Query<Page>("GetAllPages.sql").ToList();
|
|
|
|
public static void UpdatePageProcessingInstructions(int pageId, List<string> instructions)
|
|
{
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
instructions = instructions.Select(o => o.ToLower()).Distinct().ToList();
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempInstructions", instructions);
|
|
return o.Query<Page>("UpdatePageProcessingInstructions.sql", param).ToList();
|
|
});
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static Page? GetPageRevisionById(int pageId, int? revision = null)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.QuerySingleOrDefault<Page>("GetPageRevisionById.sql", param);
|
|
}
|
|
|
|
public static void SavePageSearchTokens(List<PageToken> items)
|
|
{
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var tempTable = o.CreateTempTableFrom("TempTokens", items.Distinct());
|
|
return o.Query<Page>("SavePageSearchTokens.sql").ToList();
|
|
});
|
|
}
|
|
|
|
public static void TruncateAllPageRevisions(string confirm)
|
|
{
|
|
if (confirm != "YES") //Are you REALLY sure?
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var transaction = o.BeginTransaction();
|
|
try
|
|
{
|
|
o.Execute("TruncateAllPageRevisions.sql");
|
|
transaction.Commit();
|
|
}
|
|
catch
|
|
{
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public static int GetCurrentPageRevision(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.ExecuteScalar<int>("GetCurrentPageRevision.sql", param);
|
|
}
|
|
|
|
public static int GetCurrentPageRevision(ManagedDataStorageInstance connection, int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
};
|
|
|
|
return connection.ExecuteScalar<int>("GetCurrentPageRevision.sql", param);
|
|
}
|
|
|
|
public static Page? GetLimitedPageInfoByIdAndRevision(int pageId, int? revision = null, bool allowCache = true)
|
|
{
|
|
if (allowCache)
|
|
{
|
|
var cacheKey = WikiCacheKeyFunction.Build(WikiCache.Category.Page, [pageId, revision]);
|
|
if (!WikiCache.TryGet<Page>(cacheKey, out var result))
|
|
{
|
|
if ((result = GetLimitedPageInfoByIdAndRevision(pageId, revision, false)) != null)
|
|
{
|
|
WikiCache.Put(cacheKey, result);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.QuerySingleOrDefault<Page>("GetLimitedPageInfoByIdAndRevision.sql", param);
|
|
}
|
|
|
|
public static int SavePage(Page page)
|
|
{
|
|
var pageUpsertParam = new
|
|
{
|
|
PageId = page.Id,
|
|
Name = page.Name,
|
|
Navigation = NamespaceNavigation.CleanAndValidate(page.Name),
|
|
Description = page.Description,
|
|
Body = page.Body ?? string.Empty,
|
|
Namespace = page.Namespace,
|
|
CreatedByUserId = page.CreatedByUserId,
|
|
CreatedDate = page.CreatedDate,
|
|
ModifiedByUserId = page.ModifiedByUserId,
|
|
ModifiedDate = DateTime.UtcNow
|
|
};
|
|
|
|
var newDataHash = Security.Helpers.Crc32(page.Body ?? string.Empty);
|
|
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var transaction = o.BeginTransaction();
|
|
|
|
try
|
|
{
|
|
var currentPageRevision = 0;
|
|
var hasPageChanged = false;
|
|
|
|
if (page.Id == 0)
|
|
{
|
|
page.Id = o.ExecuteScalar<int>("CreatePage.sql", pageUpsertParam);
|
|
hasPageChanged = true;
|
|
}
|
|
else
|
|
{
|
|
var currentRevisionInfo = GetLimitedPageInfoByIdAndRevision(page.Id)
|
|
?? throw new Exception("The page could not be found.");
|
|
|
|
currentPageRevision = currentRevisionInfo.Revision;
|
|
|
|
o.Execute("UpdatePage.sql", pageUpsertParam);
|
|
|
|
hasPageChanged = currentRevisionInfo.Name != page.Name
|
|
|| currentRevisionInfo.Namespace != page.Namespace
|
|
|| currentRevisionInfo.Description != page.Description
|
|
|| currentRevisionInfo.DataHash != newDataHash;
|
|
}
|
|
|
|
if (hasPageChanged)
|
|
{
|
|
currentPageRevision++;
|
|
|
|
var updatePageRevisionNumberParam = new
|
|
{
|
|
PageId = page.Id,
|
|
PageRevision = currentPageRevision
|
|
};
|
|
o.Execute("UpdatePageRevisionNumber.sql", updatePageRevisionNumberParam);
|
|
|
|
var InsertPageRevisionParam = new
|
|
{
|
|
PageId = page.Id,
|
|
Name = page.Name,
|
|
Namespace = page.Namespace,
|
|
Description = page.Description,
|
|
Body = page.Body,
|
|
DataHash = newDataHash,
|
|
PageRevision = currentPageRevision,
|
|
ModifiedByUserId = page.ModifiedByUserId,
|
|
ModifiedDate = DateTime.UtcNow,
|
|
};
|
|
o.Execute("InsertPageRevision.sql", InsertPageRevisionParam);
|
|
|
|
var reassociateAllPageAttachmentsParam = new
|
|
{
|
|
PageId = page.Id,
|
|
PageRevision = currentPageRevision,
|
|
};
|
|
o.Execute("ReassociateAllPageAttachments.sql", reassociateAllPageAttachmentsParam);
|
|
}
|
|
|
|
transaction.Commit();
|
|
}
|
|
catch
|
|
{
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
});
|
|
|
|
return page.Id;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="navigation"></param>
|
|
/// <returns></returns>
|
|
public static Page? GetPageInfoByNavigation(string navigation)
|
|
{
|
|
var param = new
|
|
{
|
|
Navigation = navigation
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.QuerySingleOrDefault<Page>("GetPageInfoByNavigation.sql", param);
|
|
}
|
|
|
|
public static int GetPageRevisionCountByPageId(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.ExecuteScalar<int>("GetPageRevisionCountByNavigation.sql", param);
|
|
}
|
|
|
|
public static void RestoreDeletedPageByPageId(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var transaction = o.BeginTransaction();
|
|
try
|
|
{
|
|
using var deletedpages_db = o.Attach("deletedpages.db", "deletedpages_db");
|
|
o.Execute("RestoreDeletedPageByPageId.sql", param);
|
|
transaction.Commit();
|
|
}
|
|
catch
|
|
{
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
});
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void MovePageRevisionToDeletedById(int pageId, int revision, Guid userId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision,
|
|
DeletedByUserId = userId,
|
|
DeletedDate = DateTime.UtcNow
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var transaction = o.BeginTransaction();
|
|
try
|
|
{
|
|
using var deletedpagerevisions_db = o.Attach("deletedpagerevisions.db", "deletedpagerevisions_db");
|
|
o.Execute("MovePageRevisionToDeletedById.sql", param);
|
|
transaction.Commit();
|
|
}
|
|
catch
|
|
{
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
});
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void MovePageToDeletedById(int pageId, Guid userId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
DeletedByUserId = userId,
|
|
DeletedDate = DateTime.UtcNow
|
|
};
|
|
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
var transaction = o.BeginTransaction();
|
|
try
|
|
{
|
|
using var deletedpages_db = o.Attach("deletedpages.db", "deletedpages_db");
|
|
|
|
o.Execute("MovePageToDeletedById.sql", param);
|
|
transaction.Commit();
|
|
ManagedDataStorage.Statistics.Execute("DeletePageStatisticsByPageId.sql", param);
|
|
}
|
|
catch
|
|
{
|
|
transaction.Rollback();
|
|
throw;
|
|
}
|
|
});
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void PurgeDeletedPageByPageId(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
ManagedDataStorage.DeletedPages.Execute("PurgeDeletedPageByPageId.sql", param);
|
|
|
|
PurgeDeletedPageRevisionsByPageId(pageId);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void PurgeDeletedPages()
|
|
{
|
|
ManagedDataStorage.DeletedPages.Execute("PurgeDeletedPages.sql");
|
|
|
|
PurgeDeletedPageRevisions();
|
|
}
|
|
|
|
public static int GetCountOfPageAttachmentsById(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.ExecuteScalar<int>("GetCountOfPageAttachmentsById.sql", param);
|
|
}
|
|
|
|
public static Page? GetDeletedPageById(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return ManagedDataStorage.DeletedPages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.QuerySingleOrDefault<Page>("GetDeletedPageById.sql", param);
|
|
});
|
|
}
|
|
|
|
public static Page? GetLatestPageRevisionById(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.QuerySingleOrDefault<Page>("GetLatestPageRevisionById.sql", param);
|
|
});
|
|
}
|
|
|
|
public static int GetPageNextRevision(int pageId, int revision)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.ExecuteScalar<int>("GetPageNextRevision.sql", param);
|
|
}
|
|
|
|
public static int GetPagePreviousRevision(int pageId, int revision)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.ExecuteScalar<int>("GetPagePreviousRevision.sql", param);
|
|
}
|
|
|
|
public static List<DeletedPageRevision> GetDeletedPageRevisionsByIdPaged(int pageId, int pageNumber,
|
|
string? orderBy = null, string? orderByDirection = null)
|
|
{
|
|
int pageSize = ConfigurationRepository.Get<int>("Customization", "Pagination Size");
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
PageNumber = pageNumber,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
return ManagedDataStorage.DeletedPageRevisions.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
|
|
var query = RepositoryHelper.TransposeOrderby("GetDeletedPageRevisionsByIdPaged.sql", orderBy,
|
|
orderByDirection);
|
|
return o.Query<DeletedPageRevision>(query, param).ToList();
|
|
});
|
|
}
|
|
|
|
public static void PurgeDeletedPageRevisions()
|
|
{
|
|
ManagedDataStorage.DeletedPageRevisions.Execute("PurgeDeletedPageRevisions.sql");
|
|
}
|
|
|
|
public static void PurgeDeletedPageRevisionsByPageId(int pageId)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
ManagedDataStorage.DeletedPageRevisions.Execute("PurgeDeletedPageRevisionsByPageId.sql", param);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void PurgeDeletedPageRevisionByPageIdAndRevision(int pageId, int revision)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
ManagedDataStorage.DeletedPageRevisions.Execute("PurgeDeletedPageRevisionByPageIdAndRevision.sql", param);
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static void RestoreDeletedPageRevisionByPageIdAndRevision(int pageId, int revision)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
ManagedDataStorage.DeletedPageRevisions.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("pages.db", "pages_db");
|
|
o.Execute("RestoreDeletedPageRevisionByPageIdAndRevision.sql", param);
|
|
});
|
|
|
|
FlushPageCache(pageId);
|
|
}
|
|
|
|
public static DeletedPageRevision? GetDeletedPageRevisionById(int pageId, int revision)
|
|
{
|
|
var param = new
|
|
{
|
|
PageId = pageId,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.DeletedPageRevisions.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.Query<DeletedPageRevision>("GetDeletedPageRevisionById.sql", param).FirstOrDefault();
|
|
});
|
|
}
|
|
|
|
public static Page? GetPageRevisionByNavigation(NamespaceNavigation navigation, int? revision = null)
|
|
{
|
|
var param = new
|
|
{
|
|
Navigation = navigation.Canonical,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.QuerySingleOrDefault<Page>("GetPageRevisionByNavigation.sql", param);
|
|
});
|
|
}
|
|
|
|
public static Page? GetPageRevisionByNavigation(string givenNavigation, int? revision = null,
|
|
bool allowCache = true)
|
|
{
|
|
var navigation = new NamespaceNavigation(givenNavigation);
|
|
|
|
if (allowCache)
|
|
{
|
|
var cacheKey = WikiCacheKeyFunction.Build(WikiCache.Category.Page, [navigation.Canonical, revision]);
|
|
if (!WikiCache.TryGet<Page>(cacheKey, out var result))
|
|
{
|
|
if ((result = GetPageRevisionByNavigation(navigation.Canonical, revision, false)) != null)
|
|
{
|
|
WikiCache.Put(cacheKey, result);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
var param = new
|
|
{
|
|
Navigation = navigation.Canonical,
|
|
Revision = revision
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var users_db = o.Attach("users.db", "users_db");
|
|
return o.QuerySingleOrDefault<Page>("GetPageRevisionByNavigation.sql", param);
|
|
});
|
|
}
|
|
|
|
#region Tags.
|
|
|
|
public static List<TagAssociation> GetAssociatedTags(string tag)
|
|
{
|
|
var param = new
|
|
{
|
|
@Tag = tag
|
|
};
|
|
|
|
return ManagedDataStorage.Pages.Query<TagAssociation>("GetAssociatedTags.sql", param).ToList();
|
|
}
|
|
|
|
public static List<Page> GetPageInfoByNamespaces(List<string> namespaces)
|
|
{
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var tempTable = o.CreateTempTableFrom("TempNamespaces", namespaces);
|
|
return o.Query<Page>("GetPageInfoByNamespaces.sql").ToList();
|
|
});
|
|
}
|
|
|
|
public static List<Page> GetPageInfoByTags(List<string> tags)
|
|
{
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var tempTable = o.CreateTempTableFrom("TempTags", tags);
|
|
return o.Query<Page>("GetPageInfoByTags.sql").ToList();
|
|
});
|
|
}
|
|
|
|
public static List<Page> GetPageInfoByTag(string tag)
|
|
{
|
|
return ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
using var tempTable = o.CreateTempTableFrom("TempTags", new List<string> { tag });
|
|
return o.Query<Page>("GetPageInfoByTags.sql").ToList();
|
|
});
|
|
}
|
|
|
|
public static void UpdatePageTags(int pageId, List<string> tags)
|
|
{
|
|
ManagedDataStorage.Pages.Ephemeral(o =>
|
|
{
|
|
tags = tags.Select(o => o.ToLower()).Distinct().ToList();
|
|
|
|
using var tempTable = o.CreateTempTableFrom("TempTags", tags);
|
|
|
|
var param = new
|
|
{
|
|
PageId = pageId
|
|
};
|
|
|
|
return o.Query<Page>("UpdatePageTags.sql", param).ToList();
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |