📄 pagesstorageprovider.cs
字号:
public PageInfo RenamePage(PageInfo page, string newName) {
if(PageExists(new PageInfo(newName, this, PageStatus.Normal, DateTime.Now))) return null;
lock(locker) {
PageInfo[] pages = AllPages;
bool found = false;
int idx = -1;
PageNameComparer comp = new PageNameComparer();
CategoryInfo[] tmp = Pages.Instance.GetCategoriesPerPage(page);
string[] cats = new string[tmp.Length];
for(int i = 0; i < tmp.Length; i++) {
cats[i] = tmp[i].Name;
}
for(int i = 0; i < pages.Length; i++) {
if(comp.Compare(pages[i], page) == 0) {
pages[i].Name = newName;
File.Copy(Settings.PagesDirectory + ((LocalPageInfo)pages[i]).File,
Settings.PagesDirectory + newName + Path.GetExtension(((LocalPageInfo)pages[i]).File));
File.Delete(Settings.PagesDirectory + ((LocalPageInfo)pages[i]).File);
((LocalPageInfo)pages[i]).File = newName + Path.GetExtension(((LocalPageInfo)pages[i]).File);
found = true;
idx = i;
break;
}
}
if(found) {
DumpPages(pages);
RenameBackups(page, newName);
Rebind(pages[idx], cats);
return pages[idx];
}
else return null;
}
}
private void RenameBackups(PageInfo page, string newName) {
List<int> backups = GetBackups(page);
LocalPageInfo pg = (LocalPageInfo)page;
for(int i = 0; i < backups.Count; i++) {
File.Copy(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i]).ToString() + Path.GetExtension(pg.File),
Settings.PagesDirectory + newName + "." + Tools.GetVersionString(backups[i]).ToString() + Path.GetExtension(pg.File), false);
File.Delete(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i]).ToString() + Path.GetExtension(pg.File));
}
}
/// <summary>
/// Sets the Status of a Page.
/// </summary>
/// <param name="page">The Page to set the Status of.</param>
/// <param name="status">The Status.</param>
/// <returns>True if the Status has been set successfully.</returns>
public PageInfo SetStatus(PageInfo page, PageStatus status) {
lock(locker) {
PageInfo[] pages = AllPages;
PageNameComparer comp = new PageNameComparer();
for(int i = 0; i < pages.Length; i++) {
if(comp.Compare(pages[i], page) == 0) {
PageInfo tmp = new LocalPageInfo(page.Name, this, status, page.CreationDateTime, ((LocalPageInfo)page).File);
pages[i] = tmp;
DumpPages(pages);
return tmp;
}
}
}
return null;
}
/// <summary>
/// Modifies the Content of a Page.
/// </summary>
/// <param name="page">The Page.</param>
/// <param name="title">The Title of the Page.</param>
/// <param name="username">The Username.</param>
/// <param name="dateTime">The Date/Time.</param>
/// <param name="comment">The comment of the editor, about this revision.</param>
/// <param name="content">The Page Content.</param>
/// <param name="backup">A value specifying whether or not to create a backup of the Page.</param>
/// <returns>True if the Page has been modified successfully.</returns>
public bool ModifyPage(PageInfo page, string title, string username, DateTime dateTime, string comment, string content, bool backup) {
if(!PageExists(page)) return false;
if(backup) Backup(page);
StringBuilder sb = new StringBuilder();
sb.Append(title);
sb.Append("\r\n");
sb.Append(username);
sb.Append("|");
sb.Append(dateTime.ToString("yyyy'/'MM'/'dd' 'HH':'mm':'ss"));
if(comment.Length > 0) {
sb.Append("|");
sb.Append(Tools.EscapeString(comment));
}
sb.Append("\r\n##PAGE##\r\n");
sb.Append(content);
Tools.WriteFile(Settings.PagesDirectory + ((LocalPageInfo)page).File, sb.ToString());
return true;
}
/// <summary>
/// Performs the rollback of a Page to a specified revision.
/// </summary>
/// <param name="page">The Page to rollback.</param>
/// <param name="revision">The Revision to rollback the Page to.</param>
/// <returns>True if the roolback succeeded.</returns>
/// <remarks>All the newer backups are deleted.</remarks>
public bool RollbackPage(PageInfo page, int revision) {
if(!PageExists(page)) return false;
List<int> backups = GetBackups(page);
if(!backups.Contains(revision)) return false;
// Operations
// - Copy the content of the specified revision into the page file
// - Delete specified revision and all the newer revisions
LocalPageInfo pg = (LocalPageInfo)page;
File.Copy(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(revision) + Path.GetExtension(pg.File),
Settings.PagesDirectory + pg.File, true);
int idx = backups.IndexOf(revision);
for(int i = backups.Count - 1; i >= idx; i--) {
File.Delete(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i]) + Path.GetExtension(pg.File));
}
return true;
}
/// <summary>
/// Deletes the Backups of a Page, up to a specified revision.
/// </summary>
/// <param name="page">The Page to delete the backups of.</param>
/// <param name="revision">The newest revision to delete (newer revision are kept) or -1 to delete all the Backups.</param>
/// <returns>True if the deletion succeeded.</returns>
public bool DeleteBackups(PageInfo page, int revision) {
lock(locker) {
List<int> backups = GetBackups(page);
if(backups.Count == 0) return true;
int idx = (revision != -1 ? backups.IndexOf(revision) : backups[backups.Count - 1]);
// Operations
// - Delete old beckups, from 0 to revision
// - Rename newer backups starting from 0
LocalPageInfo pg = (LocalPageInfo)page;
for(int i = 0; i <= idx; i++) {
File.Delete(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i]) + Path.GetExtension(pg.File));
}
if(revision != -1) {
for(int i = revision + 1; i < backups.Count; i++) {
File.Copy(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i]) + Path.GetExtension(pg.File),
Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i] - revision - 1) + Path.GetExtension(pg.File));
File.Delete(Settings.PagesDirectory + Path.GetFileNameWithoutExtension(pg.File) + "." + Tools.GetVersionString(backups[i]) + Path.GetExtension(pg.File));
}
}
}
return true;
}
/// <summary>
/// Removes a Page.
/// </summary>
/// <param name="page">The Page to remove.</param>
/// <returns>True if the Page has been removed successfully.</returns>
public bool RemovePage(PageInfo page) {
lock(locker) {
List<PageInfo> pages = new List<PageInfo>(AllPages);
PageNameComparer comp = new PageNameComparer();
for(int i = 0; i < pages.Count; i++) {
if(comp.Compare(pages[i], page) == 0) {
pages.Remove(pages[i]);
DumpPages(pages.ToArray());
DeleteBackups(page, -1);
try {
File.Delete(Settings.PagesDirectory + ((LocalPageInfo)page).File);
File.Delete(Settings.MessagesDirectory + ((LocalPageInfo)page).File);
}
catch { }
return true;
}
}
}
return false;
}
/// <summary>
/// Binds a Page with one or more Categories.
/// </summary>
/// <param name="page">The Page to bind.</param>
/// <param name="categories">The Categories to bind the Page with.</param>
/// <returns>True if the binding succeeded.</returns>
/// <remarks>After a successful operation, the Page is binded with all and only the categories passed as argument.</remarks>
public bool Rebind(PageInfo page, string[] categories) {
lock(locker) {
if(!PageExists(page)) return false;
CategoryInfo[] cats = AllCategories;
// Operations:
// - Remove the Page from every Category
// - For each specified category, add (if needed) the Page
List<string> pages;
CategoryNameComparer catComp = new CategoryNameComparer();
for(int i = 0; i < cats.Length; i++) {
pages = new List<string>(cats[i].Pages);
int idx = Contains(pages, page.Name);
if(idx != -1) pages.Remove(pages[idx]);
cats[i].Pages = pages.ToArray();
}
for(int i = 0; i < cats.Length; i++) {
for(int k = 0; k < categories.Length; k++) {
if(catComp.Compare(cats[i], new CategoryInfo(categories[k], this)) == 0) {
pages = new List<string>(cats[i].Pages);
pages.Add(page.Name);
cats[i].Pages = pages.ToArray();
}
}
}
DumpCategories(cats);
}
return true;
}
private int Contains(List<string> pages, string page) {
PageNameComparer comp = new PageNameComparer();
for(int i = 0; i < pages.Count; i++) {
if(pages[i].ToLower().Equals(page.ToLower())) return i;
}
return -1;
}
private void DumpPages(PageInfo[] pages) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < pages.Length; i++) {
sb.Append(pages[i].Name);
sb.Append("|");
sb.Append(((LocalPageInfo)pages[i]).File);
switch(pages[i].Status) {
case PageStatus.Normal:
sb.Append("|NORMAL");
break;
case PageStatus.Locked:
sb.Append("|LOCKED");
break;
case PageStatus.Public:
sb.Append("|PUBLIC");
break;
}
sb.Append("|");
sb.Append(pages[i].CreationDateTime.ToString("yyyy'/'MM'/'dd' 'HH':'mm':'ss"));
if(i != pages.Length - 1) sb.Append("\r\n");
}
Tools.WriteFile(Settings.PagesFile, sb.ToString());
}
private void DumpCategories(CategoryInfo[] categories) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < categories.Length; i++) {
sb.Append(categories[i].Name);
if(categories[i].Pages.Length > 0) {
for(int k = 0; k < categories[i].Pages.Length; k++) {
sb.Append("|");
sb.Append(categories[i].Pages[k]);
}
}
sb.Append("\r\n");
}
Tools.WriteFile(Settings.CategoriesFile, sb.ToString());
}
/// <summary>
/// Gets the Page Messages.
/// </summary>
/// <param name="page">The Page.</param>
/// <returns>The list of the <b>first-level</b> Messages, containing the replies properly nested.</returns>
public Message[] GetMessages(PageInfo page) {
LocalPageInfo pg = (LocalPageInfo)page;
// Shortcut
if(!File.Exists(Settings.MessagesDirectory + pg.File)) return new Message[0];
string data;
lock(lockerDisc) {
data = Tools.LoadFile(Settings.MessagesDirectory + pg.File).Replace("\r", "");
}
string[] lines = data.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
List<Message> result = new List<Message>();
// Structure
// ID|Username|Subject|DateTime|ParentID|Body
// This algorithm DOES not handle replies that are stored BEFORE their parent,
// so every reply MUST be stored anywhere but AFTER its parent
// (the message tree should be stored depht-first; new messages can be appended at the end of the file)
string[] fields;
int id, parent;
string username, subject, body;
DateTime dateTime;
for(int i = 0; i < lines.Length; i++) {
fields = lines[i].Split('|');
id = int.Parse(fields[0]);
username = fields[1];
subject = Tools.UnescapeString(fields[2]);
dateTime = DateTime.Parse(fields[3]);
parent = int.Parse(fields[4]);
body = Tools.UnescapeString(fields[5]);
if(parent != -1) {
// Find parent
Message p = FindMessage(result, parent);
if(p == null) {
// Add as top-level message
result.Add(new Message(id, username, subject, dateTime, body));
}
else {
// Add to parent's replies
p.Replies.Add(new Message(id, username, subject, dateTime, body));
}
}
else {
// Add as top-level message
result.Add(new Message(id, username, subject, dateTime, body));
}
}
return result.ToArray();
}
/// <summary>
/// Gets the total number of Messages in a Page Discussion.
/// </summary>
/// <param name="page">The Page.</param>
/// <returns>The number of messages.</returns>
public int GetMessageCount(PageInfo page) {
LocalPageInfo pg = (LocalPageInfo)page;
if(!File.Exists(Settings.MessagesDirectory + pg.File)) return 0;
string data = Tools.LoadFile(Settings.MessagesDirectory + pg.File).Replace("\r", "");
return data.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
/// <summary>
/// Finds a Message in a Message tree.
/// </summary>
/// <param name="messages">The Message tree.</param>
/// <param name="id">The ID of the Message to find.</param>
/// <returns>The Message or null.</returns>
/// <remarks>The method is recursive.</remarks>
private Message FindMessage(List<Message> messages, int id) {
Message result = null;
for(int i = 0; i < messages.Count; i++) {
if(messages[i].ID == id) {
result = messages[i];
}
if(result == null) {
result = FindMessage(messages[i].Replies, id);
}
if(result != null) break;
}
return result;
}
/// <summary>
/// Adds a new Message to a Page.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -