diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 0e4cd99..a89dec1 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -1012 \ No newline at end of file +1034 \ No newline at end of file diff --git a/Common/Common.csproj b/Common/Common.csproj index 331fb91..f7812db 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -100,6 +100,7 @@ + diff --git a/Common/TableManager.cs b/Common/TableManager.cs index 66a5cfb..523f437 100644 --- a/Common/TableManager.cs +++ b/Common/TableManager.cs @@ -18,11 +18,12 @@ namespace FLocal.Common { dataobjects.Moderator.TableSpec.instance, dataobjects.PMConversation.TableSpec.instance, dataobjects.PMMessage.TableSpec.instance, - dataobjects.Punishment.TableSpec.instance, - dataobjects.PunishmentType.TableSpec.instance, dataobjects.Poll.TableSpec.instance, dataobjects.Post.TableSpec.instance, dataobjects.PostLayer.TableSpec.instance, + dataobjects.Punishment.TableSpec.instance, + dataobjects.PunishmentTransfer.TableSpec.instance, + dataobjects.PunishmentType.TableSpec.instance, dataobjects.QuickLink.TableSpec.instance, dataobjects.Revision.TableSpec.instance, dataobjects.Session.TableSpec.instance, diff --git a/Common/actions/ChangeSet.cs b/Common/actions/ChangeSet.cs index ac2878a..9d8531d 100644 --- a/Common/actions/ChangeSet.cs +++ b/Common/actions/ChangeSet.cs @@ -36,6 +36,7 @@ namespace FLocal.Common.actions { dataobjects.Invite.TableSpec.TABLE, dataobjects.Moderator.TableSpec.TABLE, dataobjects.Punishment.TableSpec.TABLE, + dataobjects.PunishmentTransfer.TableSpec.TABLE, dataobjects.Session.TableSpec.TABLE, } ); diff --git a/Common/actions/IncrementFieldValue.cs b/Common/actions/IncrementFieldValue.cs index d1bffca..f7d8be2 100644 --- a/Common/actions/IncrementFieldValue.cs +++ b/Common/actions/IncrementFieldValue.cs @@ -6,8 +6,21 @@ using System.Text; namespace FLocal.Common.actions { class IncrementFieldValue : AbstractFieldValue { - public static readonly Func INCREMENTOR = s => (int.Parse(s)+1).ToString(); - public static readonly Func DECREMENTOR = s => (int.Parse(s)-1).ToString(); + public static Func INCREMENTOR_CUSTOM(int i) { + return s => (int.Parse(s)+i).ToString(); + } + + public static Func DECREMENTOR_CUSTOM(int i) { + return s => (int.Parse(s)-i).ToString(); + } + + public static string INCREMENTOR(string s) { + return INCREMENTOR_CUSTOM(1)(s); + } + + public static string DECREMENTOR(string s) { + return DECREMENTOR_CUSTOM(1)(s); + } public static Func GREATEST(int val) { return s => { diff --git a/Common/dataobjects/Board.cs b/Common/dataobjects/Board.cs index b27e2b9..2fb89c4 100644 --- a/Common/dataobjects/Board.cs +++ b/Common/dataobjects/Board.cs @@ -11,6 +11,13 @@ using FLocal.Common.actions; namespace FLocal.Common.dataobjects { public class Board : SqlObject { + [Flags] + public enum SubboardsOptions { + None = 0x0, + FirstLevel = 0x1, + AllLevels = 0x3 + } + public class TableSpec : IComplexSqlObjectTableSpec { public const string TABLE = "Boards"; public const string FIELD_ID = "Id"; @@ -209,7 +216,7 @@ namespace FLocal.Common.dataobjects { ); } - public XElement exportToXml(UserContext context, bool includeSubBoards, params XElement[] additional) { + public XElement exportToXml(UserContext context, Board.SubboardsOptions subboardsOptions, params XElement[] additional) { XElement result = new XElement("board", new XElement("id", this.id), new XElement("sortOrder", this.sortOrder), @@ -226,9 +233,9 @@ namespace FLocal.Common.dataobjects { result.Add(new XElement("hasNewPosts", this.hasNewPosts(context.account).ToPlainString())); } - if(includeSubBoards) { + if((subboardsOptions & SubboardsOptions.FirstLevel) == SubboardsOptions.FirstLevel) { result.Add(new XElement("subBoards", - from board in this.subBoards select board.exportToXml(context, false) + from board in this.subBoards select board.exportToXml(context, (subboardsOptions == SubboardsOptions.AllLevels) ? SubboardsOptions.AllLevels : SubboardsOptions.None) )); } @@ -382,5 +389,23 @@ namespace FLocal.Common.dataobjects { return Thread.LoadById(threadInsert.getId().Value); } + public readonly object locker = new object(); + + public void Synchronized(Action action) { + lock(this.locker) { + if(this.parentBoardId.HasValue) { + this.parentBoard.Synchronized(action); + } else { + action(); + } + } + } + + public IEnumerable boardAndParents { + get { + return this.ToSequence(board => board.parentBoardId.HasValue ? new Board[] { board.parentBoard } : new Board[0]); + } + } + } } diff --git a/Common/dataobjects/Category.cs b/Common/dataobjects/Category.cs index 181313c..93a4d7c 100644 --- a/Common/dataobjects/Category.cs +++ b/Common/dataobjects/Category.cs @@ -110,12 +110,12 @@ namespace FLocal.Common.dataobjects { ); } - public XElement exportToXmlForMainPage(UserContext context) { + public XElement exportToXmlForMainPage(UserContext context, Board.SubboardsOptions subboardsOptions) { return new XElement("category", new XElement("id", this.id), new XElement("name", this.name), new XElement("sortOrder", this.sortOrder), - new XElement("boards", from board in this.subBoards select board.exportToXml(context, true)) + new XElement("boards", from board in this.subBoards select board.exportToXml(context, subboardsOptions)) ); } diff --git a/Common/dataobjects/Post.cs b/Common/dataobjects/Post.cs index 10ed61b..12d1889 100644 --- a/Common/dataobjects/Post.cs +++ b/Common/dataobjects/Post.cs @@ -281,10 +281,15 @@ namespace FLocal.Common.dataobjects { PostLayer actualLayer = poster.getActualLayer(this.thread.board, desiredLayer); - var changes = Thread.getNewPostChanges(this.thread.board, this.threadId, this, poster, actualLayer, title, body, date, forcedPostId); - ChangeSetUtil.ApplyChanges(changes.Value.ToArray()); - - return Post.LoadById(changes.Key.getId().Value); + Post newPost; + lock(this.thread.locker) { + + var changes = Thread.getNewPostChanges(this.thread.board, this.threadId, this, poster, actualLayer, title, body, date, forcedPostId); + ChangeSetUtil.ApplyChanges(changes.Value.ToArray()); + + newPost = Post.LoadById(changes.Key.getId().Value); + } + return newPost; } private readonly object Edit_locker = new object(); //TODO: move locking to DB @@ -335,8 +340,24 @@ namespace FLocal.Common.dataobjects { } } + private IEnumerable subPosts { + get { + return Post.LoadByIds( + from stringId in Config.instance.mainConnection.LoadIdsByConditions( + TableSpec.instance, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_PARENTPOSTID), + ComparisonType.EQUAL, + this.id.ToString() + ), + Diapasone.unlimited + ) select int.Parse(stringId) + ); + } + } + private readonly object Punish_Locker = new object(); - public void Punish(Account account, PunishmentType type, string comment) { + public void Punish(Account account, PunishmentType type, string comment, PunishmentTransfer.NewTransferInfo? transferInfo) { if(!Moderator.isModerator(account, this.thread.board)) throw new FLocalException(account.id + " is not a moderator in board " + this.thread.board.id); @@ -344,62 +365,205 @@ namespace FLocal.Common.dataobjects { lock(this.Punish_Locker) { - List changes = ( - from punishment in this.punishments - select (AbstractChange)new UpdateChange( - Punishment.TableSpec.instance, - new Dictionary { - { Punishment.TableSpec.FIELD_ISWITHDRAWED, new ScalarFieldValue("1") }, - }, - punishment.id - ) - ).ToList(); + lock(this.thread.locker) { - changes.Add( - new UpdateChange( - TableSpec.instance, - new Dictionary { - { TableSpec.FIELD_TOTALPUNISHMENTS, new IncrementFieldValue() }, - }, - this.id - ) - ); + IEnumerable changes = ( + from punishment in this.punishments + select (AbstractChange)new UpdateChange( + Punishment.TableSpec.instance, + new Dictionary { + { Punishment.TableSpec.FIELD_ISWITHDRAWED, new ScalarFieldValue("1") }, + }, + punishment.id + ) + ); - changes.Add( - new InsertChange( - Punishment.TableSpec.instance, - new Dictionary { - { Punishment.TableSpec.FIELD_POSTID, new ScalarFieldValue(this.id.ToString()) }, - { Punishment.TableSpec.FIELD_OWNERID, new ScalarFieldValue(this.poster.id.ToString()) }, - { Punishment.TableSpec.FIELD_ORIGINALBOARDID, new ScalarFieldValue(this.thread.board.id.ToString()) }, - { Punishment.TableSpec.FIELD_MODERATORID, new ScalarFieldValue(account.id.ToString()) }, - { Punishment.TableSpec.FIELD_PUNISHMENTDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, - { Punishment.TableSpec.FIELD_PUNISHMENTTYPE, new ScalarFieldValue(type.id.ToString()) }, - { Punishment.TableSpec.FIELD_ISWITHDRAWED, new ScalarFieldValue("0") }, - { Punishment.TableSpec.FIELD_COMMENT, new ScalarFieldValue(comment) }, - { Punishment.TableSpec.FIELD_EXPIRES, new ScalarFieldValue(DateTime.Now.Add(type.timeSpan).ToUTCString()) }, - } - ) - ); + InsertChange transferInsert = null; + + + if(transferInfo.HasValue) { + + var _transferInfo = transferInfo.Value; + + Post lastAffectedPost; + int totalAffectedPosts; + + if(!this.parentPostId.HasValue) { + if(!_transferInfo.isSubthreadTransfer) { + throw new FLocalException("You cannot move the first post in thread"); + } else { + lastAffectedPost = this.thread.lastPost; + totalAffectedPosts = this.thread.totalPosts; + changes = changes.Union( + new UpdateChange( + Thread.TableSpec.instance, + new Dictionary { + { Thread.TableSpec.FIELD_BOARDID, new ScalarFieldValue(_transferInfo.newBoardId.ToString()) }, + }, + this.thread.id + ) + ); + } + } else { + + List postsAffected; + if(_transferInfo.isSubthreadTransfer) { + postsAffected = this.ToSequence(post => post.subPosts).OrderBy(post => post.id).ToList(); + } else { + postsAffected = new List(); + postsAffected.Add(this); + } + + lastAffectedPost = postsAffected.Last(); + totalAffectedPosts = postsAffected.Count; + + InsertChange threadCreate = new InsertChange( + Thread.TableSpec.instance, + new Dictionary { + { Thread.TableSpec.FIELD_BOARDID, new ScalarFieldValue(_transferInfo.newBoardId.ToString()) }, + { Thread.TableSpec.FIELD_FIRSTPOSTID, new ScalarFieldValue(this.id.ToString()) }, + { Thread.TableSpec.FIELD_ISANNOUNCEMENT, new ScalarFieldValue("0") }, + { Thread.TableSpec.FIELD_ISLOCKED, new ScalarFieldValue("0") }, + { Thread.TableSpec.FIELD_LASTPOSTDATE, new ScalarFieldValue(lastAffectedPost.postDate.ToUTCString()) }, + { Thread.TableSpec.FIELD_LASTPOSTID, new ScalarFieldValue(lastAffectedPost.id.ToString()) }, + { Thread.TableSpec.FIELD_TITLE, new ScalarFieldValue(this.title) }, + { Thread.TableSpec.FIELD_TOPICSTARTERID, new ScalarFieldValue(this.posterId.ToString()) }, + { Thread.TableSpec.FIELD_TOTALPOSTS, new ScalarFieldValue(totalAffectedPosts.ToString()) }, + { Thread.TableSpec.FIELD_TOTALVIEWS, new ScalarFieldValue("0") }, + } + ); + changes = changes.Union(threadCreate); + + changes = changes.Union( + from post in postsAffected + select (AbstractChange)new UpdateChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_THREADID, new ReferenceFieldValue(threadCreate) }, + }, + post.id + ) + ); + + if(!_transferInfo.isSubthreadTransfer) { + changes = changes.Union( + from post in this.subPosts + select (AbstractChange)new UpdateChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_PARENTPOSTID, new ScalarFieldValue(this.parentPostId.ToString()) }, + }, + post.id + ) + ); + } - ChangeSetUtil.ApplyChanges(changes.ToArray()); + } - this.punishments_Reset(); + changes = changes.Union( + from board in this.thread.board.boardAndParents + select (AbstractChange)new UpdateChange( + Board.TableSpec.instance, + new Dictionary { + { Board.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue(IncrementFieldValue.DECREMENTOR_CUSTOM(totalAffectedPosts)) }, + { Board.TableSpec.FIELD_TOTALTHREADS, new IncrementFieldValue(IncrementFieldValue.DECREMENTOR_CUSTOM(this.parentPostId.HasValue ? 0 : 1)) }, + }, + board.id + ) + ); + + changes = changes.Union( + from board in _transferInfo.newBoard.boardAndParents + select (AbstractChange)new UpdateChange( + Board.TableSpec.instance, + new Dictionary { + { Board.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue(IncrementFieldValue.INCREMENTOR_CUSTOM(totalAffectedPosts)) }, + { Board.TableSpec.FIELD_TOTALTHREADS, new IncrementFieldValue() }, + { Board.TableSpec.FIELD_LASTPOSTID, new IncrementFieldValue(IncrementFieldValue.GREATEST(lastAffectedPost.id)) }, + }, + board.id + ) + ); + + transferInsert = new InsertChange( + PunishmentTransfer.TableSpec.instance, + new Dictionary { + { PunishmentTransfer.TableSpec.FIELD_OLDBOARDID, new ScalarFieldValue(this.thread.boardId.ToString()) }, + { PunishmentTransfer.TableSpec.FIELD_NEWBOARDID, new ScalarFieldValue(_transferInfo.newBoardId.ToString()) }, + { PunishmentTransfer.TableSpec.FIELD_ISSUBTHREADTRANSFER, new ScalarFieldValue(_transferInfo.isSubthreadTransfer.ToDBString()) }, + { PunishmentTransfer.TableSpec.FIELD_OLDPARENTPOSTID, new ScalarFieldValue(this.parentPostId.HasValue ? this.parentPostId.ToString() : null) }, + } + ); + changes = changes.Union(transferInsert); + + changes = changes.Union( + new UpdateChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_PARENTPOSTID, new ScalarFieldValue(null) }, + }, + this.id + ) + ); + + if(this.parentPostId.HasValue) { + changes = changes.Union( + new UpdateChange( + Thread.TableSpec.instance, + new Dictionary { + { Thread.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue(IncrementFieldValue.DECREMENTOR_CUSTOM(totalAffectedPosts)) }, + }, + this.threadId + ) + ); + } + } - Account posterAccount = null; - try { - posterAccount = Account.LoadByUser(this.poster); - } catch(NotFoundInDBException) { - } - - if(posterAccount != null) { - PMMessage newMessage = PMConversation.SendPMMessage( - account, - posterAccount, - this.title, - String.Format("{0}\r\n[post]{2}[/post]\r\n{1}", type.description, comment, this.id) + changes = changes.Union( + new UpdateChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_TOTALPUNISHMENTS, new IncrementFieldValue() }, + }, + this.id + ), + new InsertChange( + Punishment.TableSpec.instance, + new Dictionary { + { Punishment.TableSpec.FIELD_POSTID, new ScalarFieldValue(this.id.ToString()) }, + { Punishment.TableSpec.FIELD_OWNERID, new ScalarFieldValue(this.poster.id.ToString()) }, + { Punishment.TableSpec.FIELD_ORIGINALBOARDID, new ScalarFieldValue(this.thread.board.id.ToString()) }, + { Punishment.TableSpec.FIELD_MODERATORID, new ScalarFieldValue(account.id.ToString()) }, + { Punishment.TableSpec.FIELD_PUNISHMENTDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { Punishment.TableSpec.FIELD_PUNISHMENTTYPE, new ScalarFieldValue(type.id.ToString()) }, + { Punishment.TableSpec.FIELD_ISWITHDRAWED, new ScalarFieldValue("0") }, + { Punishment.TableSpec.FIELD_COMMENT, new ScalarFieldValue(comment) }, + { Punishment.TableSpec.FIELD_EXPIRES, new ScalarFieldValue(DateTime.Now.Add(type.timeSpan).ToUTCString()) }, + { Punishment.TableSpec.FIELD_TRANSFERID, (transferInsert != null) ? (AbstractFieldValue)new ReferenceFieldValue(transferInsert) : (AbstractFieldValue)new ScalarFieldValue(null) }, + } + ) ); - newMessage.conversation.markAsRead(account, newMessage, newMessage); + + ChangeSetUtil.ApplyChanges(changes.ToArray()); + + this.punishments_Reset(); + + Account posterAccount = null; + try { + posterAccount = Account.LoadByUser(this.poster); + } catch(NotFoundInDBException) { + } + + if(posterAccount != null) { + PMMessage newMessage = PMConversation.SendPMMessage( + account, + posterAccount, + this.title, + String.Format("{0}\r\n[post]{2}[/post]\r\n{1}", type.description, comment, this.id) + ); + newMessage.conversation.markAsRead(account, newMessage, newMessage); + } + } } } diff --git a/Common/dataobjects/Punishment.cs b/Common/dataobjects/Punishment.cs index 28c06a0..9d57b24 100644 --- a/Common/dataobjects/Punishment.cs +++ b/Common/dataobjects/Punishment.cs @@ -22,6 +22,7 @@ namespace FLocal.Common.dataobjects { public const string FIELD_ISWITHDRAWED = "IsWithdrawed"; public const string FIELD_COMMENT = "Comment"; public const string FIELD_EXPIRES = "Expires"; + public const string FIELD_TRANSFERID = "TransferId"; public static readonly TableSpec instance = new TableSpec(); public string name { get { return TABLE; } } public string idName { get { return FIELD_ID; } } @@ -127,6 +128,19 @@ namespace FLocal.Common.dataobjects { } } + private int? _transferId; + public int? transferId { + get { + this.LoadIfNotLoaded(); + return this._transferId; + } + } + public PunishmentTransfer transfer { + get { + return PunishmentTransfer.LoadById(this.transferId.Value); + } + } + protected override void doFromHash(Dictionary data) { this._postId = int.Parse(data[TableSpec.FIELD_POSTID]); this._ownerId = int.Parse(data[TableSpec.FIELD_OWNERID]); @@ -137,6 +151,7 @@ namespace FLocal.Common.dataobjects { this._isWithdrawed = Util.string2bool(data[TableSpec.FIELD_ISWITHDRAWED]); this._comment = data[TableSpec.FIELD_COMMENT]; this._expires = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_EXPIRES]).Value; + this._transferId = Util.ParseInt(data[TableSpec.FIELD_TRANSFERID]); } public XElement exportToXml(UserContext context) { @@ -149,7 +164,8 @@ namespace FLocal.Common.dataobjects { this.punishmentType.exportToXml(context), new XElement("isWithdrawed", this.isWithdrawed.ToPlainString()), new XElement("comment", this.comment), - new XElement("expires", this.expires) + new XElement("expires", this.expires), + this.transferId.HasValue ? this.transfer.exportToXml(context) : null ); } diff --git a/Common/dataobjects/PunishmentTransfer.cs b/Common/dataobjects/PunishmentTransfer.cs new file mode 100644 index 0000000..397296c --- /dev/null +++ b/Common/dataobjects/PunishmentTransfer.cs @@ -0,0 +1,111 @@ +п»їusing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using FLocal.Core; +using FLocal.Core.DB; +using FLocal.Core.DB.conditions; + +namespace FLocal.Common.dataobjects { + public class PunishmentTransfer : SqlObject { + + public struct NewTransferInfo { + + public readonly int newBoardId; + public Board newBoard { + get { + return Board.LoadById(this.newBoardId); + } + } + + public readonly bool isSubthreadTransfer; + + public NewTransferInfo(Board newBoard, bool isSubthreadTransfer) { + this.newBoardId = newBoard.id; + this.isSubthreadTransfer = isSubthreadTransfer; + } + + } + + public class TableSpec : ISqlObjectTableSpec { + public const string TABLE = "PunishmentTransfers"; + public const string FIELD_ID = "Id"; + public const string FIELD_OLDBOARDID = "OldBoardId"; + public const string FIELD_OLDPARENTPOSTID = "OldParentPostId"; + public const string FIELD_NEWBOARDID = "NewBoardId"; + public const string FIELD_ISSUBTHREADTRANSFER = "IsSubthreadMove"; + public static readonly TableSpec instance = new TableSpec(); + public string name { get { return TABLE; } } + public string idName { get { return FIELD_ID; } } + public void refreshSqlObject(int id) { Refresh(id); } + } + + protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } + + private int _oldBoardId; + public int oldBoardId { + get { + this.LoadIfNotLoaded(); + return this._oldBoardId; + } + } + public Board oldBoard { + get { + return Board.LoadById(this.oldBoardId); + } + } + + private int? _oldParentPostId; + public int? oldParentPostId { + get { + this.LoadIfNotLoaded(); + return this._oldParentPostId; + } + } + public Post oldParentPost { + get { + return Post.LoadById(this.oldParentPostId.Value); + } + } + + private int _newBoardId; + public int newBoardId { + get { + this.LoadIfNotLoaded(); + return this._newBoardId; + } + } + public Board newBoard { + get { + return Board.LoadById(this.newBoardId); + } + } + + private bool _isSubthreadTransfer; + public bool isSubthreadTransfer { + get { + this.LoadIfNotLoaded(); + return this._isSubthreadTransfer; + } + } + + protected override void doFromHash(Dictionary data) { + this._oldBoardId = int.Parse(data[TableSpec.FIELD_OLDBOARDID]); + this._oldParentPostId = Util.ParseInt(data[TableSpec.FIELD_OLDPARENTPOSTID]); + this._newBoardId = int.Parse(data[TableSpec.FIELD_NEWBOARDID]); + this._isSubthreadTransfer = Util.string2bool(data[TableSpec.FIELD_ISSUBTHREADTRANSFER]); + } + + public XElement exportToXml(UserContext context) { + return new XElement("transfer", + new XElement("id", this.id), + new XElement("oldBoard", this.oldBoard.exportToXmlSimple(context)), + this.oldParentPostId.HasValue ? new XElement("oldParentPost", this.oldParentPost.exportToXmlBase(context)) : null, + new XElement("newBoard", this.newBoard.exportToXmlSimple(context)), + new XElement("isSubthreadTransfer", this.isSubthreadTransfer.ToPlainString()) + ); + } + + } +} diff --git a/Common/dataobjects/Thread.cs b/Common/dataobjects/Thread.cs index bab5fad..9654521 100644 --- a/Common/dataobjects/Thread.cs +++ b/Common/dataobjects/Thread.cs @@ -470,6 +470,14 @@ namespace FLocal.Common.dataobjects { return new KeyValuePair>(postInsert, changes); } + public readonly object locker = new object(); + + public void Synchronized(Action action) { + lock(this.locker) { + this.board.Synchronized(action); + } + } + } } diff --git a/Core/extensions/Extensions.cs b/Core/extensions/Extensions.cs index 1887b6c..d43904d 100644 --- a/Core/extensions/Extensions.cs +++ b/Core/extensions/Extensions.cs @@ -57,7 +57,7 @@ namespace FLocal.Core { return string.Join(",", (from elem in list select elem.ToString()).ToArray()); } - public static string ToXmlApiRequestString(this bool val) { + public static string ToDBString(this bool val) { return val ? "1" : "0"; } @@ -230,5 +230,22 @@ namespace FLocal.Core { return date.ToUniversalTime().ToString("u"); } + public static IEnumerable ToSequence(this T obj, Func> nextElementsGenerator) where T : class { + yield return obj; + foreach(var sub in nextElementsGenerator(obj)) { + foreach(var subsub in sub.ToSequence(nextElementsGenerator)) { + yield return subsub; + } + } + } + + public static T Last(this List list) { + return list[list.Count-1]; + } + + public static IEnumerable Union(this IEnumerable enumerable, params T[] second) { + return enumerable.Union((IEnumerable)second); + } + } } diff --git a/IISMainHandler/handlers/BoardHandler.cs b/IISMainHandler/handlers/BoardHandler.cs index 2f8535a..ecb8bd8 100644 --- a/IISMainHandler/handlers/BoardHandler.cs +++ b/IISMainHandler/handlers/BoardHandler.cs @@ -25,7 +25,7 @@ namespace FLocal.IISHandler.handlers { IEnumerable threads = board.getThreads(pageOuter); XElement[] result = new XElement[] { new XElement("currentLocation", board.exportToXmlSimpleWithParent(context)), - new XElement("boards", from subBoard in board.subBoards select subBoard.exportToXml(context, true)), + new XElement("boards", from subBoard in board.subBoards select subBoard.exportToXml(context, Board.SubboardsOptions.FirstLevel)), new XElement("threads", from thread in threads select thread.exportToXml(context), pageOuter.exportToXml(1, 5, 1) diff --git a/IISMainHandler/handlers/BoardsHandler.cs b/IISMainHandler/handlers/BoardsHandler.cs index aba4e20..5194088 100644 --- a/IISMainHandler/handlers/BoardsHandler.cs +++ b/IISMainHandler/handlers/BoardsHandler.cs @@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers { override protected IEnumerable getSpecificData(WebContext context) { return new XElement[] { - new XElement("categories", from category in Category.allCategories select category.exportToXmlForMainPage(context)), + new XElement("categories", from category in Category.allCategories select category.exportToXmlForMainPage(context, Board.SubboardsOptions.FirstLevel)), new XElement("totalRegistered", Config.instance.mainConnection.GetCountByConditions(User.TableSpec.instance, new EmptyCondition())), new XElement("activity", new XElement("threshold", Config.instance.ActivityThreshold.ToString()), diff --git a/IISMainHandler/handlers/request/CreateThreadHandler.cs b/IISMainHandler/handlers/request/CreateThreadHandler.cs index fdf3195..8dd9396 100644 --- a/IISMainHandler/handlers/request/CreateThreadHandler.cs +++ b/IISMainHandler/handlers/request/CreateThreadHandler.cs @@ -24,7 +24,7 @@ namespace FLocal.IISHandler.handlers.request { newThread.markAsRead(context.session.account, newPost, newPost); return new XElement[] { - newThread.board.exportToXml(context, false), + newThread.board.exportToXml(context, Board.SubboardsOptions.None), newPost.exportToXml(context) }; } diff --git a/IISMainHandler/handlers/request/EditHandler.cs b/IISMainHandler/handlers/request/EditHandler.cs index 1c38f57..40b6a06 100644 --- a/IISMainHandler/handlers/request/EditHandler.cs +++ b/IISMainHandler/handlers/request/EditHandler.cs @@ -26,7 +26,7 @@ namespace FLocal.IISHandler.handlers.request { ); return new XElement[] { - post.thread.board.exportToXml(context, false), + post.thread.board.exportToXml(context, Board.SubboardsOptions.None), postXml }; } diff --git a/IISMainHandler/handlers/request/PunishHandler.cs b/IISMainHandler/handlers/request/PunishHandler.cs index 853fe9f..4c41c5f 100644 --- a/IISMainHandler/handlers/request/PunishHandler.cs +++ b/IISMainHandler/handlers/request/PunishHandler.cs @@ -21,11 +21,16 @@ namespace FLocal.IISHandler.handlers.request { post.Punish( context.session.account, PunishmentType.LoadById(int.Parse(context.httprequest.Form["punishmentTypeId"])), - context.httprequest.Form["comment"] + context.httprequest.Form["comment"], + (context.httprequest.Form["transfer"] == "transfer") + ? + (PunishmentTransfer.NewTransferInfo?)new PunishmentTransfer.NewTransferInfo(Board.LoadById(int.Parse(context.httprequest.Form["transfer_boardId"])), context.httprequest.Form["transfer_subThread"] == "transfer_subThread") + : + null ); return new XElement[] { - post.thread.board.exportToXml(context, false), + post.thread.board.exportToXml(context, Board.SubboardsOptions.None), postXml }; } diff --git a/IISMainHandler/handlers/request/ReplyHandler.cs b/IISMainHandler/handlers/request/ReplyHandler.cs index 35f14a7..cc51ef8 100644 --- a/IISMainHandler/handlers/request/ReplyHandler.cs +++ b/IISMainHandler/handlers/request/ReplyHandler.cs @@ -24,7 +24,7 @@ namespace FLocal.IISHandler.handlers.request { newPost.thread.markAsRead(context.session.account, newPost, newPost); return new XElement[] { - newPost.thread.board.exportToXml(context, false), + newPost.thread.board.exportToXml(context, Board.SubboardsOptions.None), newPost.exportToXml(context) }; } diff --git a/IISMainHandler/handlers/response/BoardAsThread.cs b/IISMainHandler/handlers/response/BoardAsThread.cs index f9a1cdb..e82a85b 100644 --- a/IISMainHandler/handlers/response/BoardAsThread.cs +++ b/IISMainHandler/handlers/response/BoardAsThread.cs @@ -32,7 +32,7 @@ namespace FLocal.IISHandler.handlers.response { ); return new XElement[] { new XElement("currentLocation", board.exportToXmlSimpleWithParent(context)), - new XElement("boards", from subBoard in board.subBoards select subBoard.exportToXml(context, true)), + new XElement("boards", from subBoard in board.subBoards select subBoard.exportToXml(context, Board.SubboardsOptions.FirstLevel)), new XElement("posts", from thread in threads select thread.firstPost.exportToXml( context, diff --git a/IISMainHandler/handlers/response/CreateThreadHandler.cs b/IISMainHandler/handlers/response/CreateThreadHandler.cs index ad1ebcb..3eab456 100644 --- a/IISMainHandler/handlers/response/CreateThreadHandler.cs +++ b/IISMainHandler/handlers/response/CreateThreadHandler.cs @@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers.response { Board board = Board.LoadById(int.Parse(context.requestParts[1])); return new XElement[] { - board.exportToXml(context, false), + board.exportToXml(context, Board.SubboardsOptions.None), new XElement("layers", from layer in PostLayer.allLayers select layer.exportToXml(context) ), diff --git a/IISMainHandler/handlers/response/EditHandler.cs b/IISMainHandler/handlers/response/EditHandler.cs index 248d74b..59a6e0a 100644 --- a/IISMainHandler/handlers/response/EditHandler.cs +++ b/IISMainHandler/handlers/response/EditHandler.cs @@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers.response { Post post = Post.LoadById(int.Parse(context.requestParts[1])); return new XElement[] { - post.thread.board.exportToXml(context, false), + post.thread.board.exportToXml(context, Board.SubboardsOptions.None), post.thread.exportToXml(context), post.exportToXml(context), post.latestRevision.exportToXml(context), diff --git a/IISMainHandler/handlers/response/PMReplyToPostHandler.cs b/IISMainHandler/handlers/response/PMReplyToPostHandler.cs index 2434e91..4441b18 100644 --- a/IISMainHandler/handlers/response/PMReplyToPostHandler.cs +++ b/IISMainHandler/handlers/response/PMReplyToPostHandler.cs @@ -31,7 +31,7 @@ namespace FLocal.IISHandler.handlers.response { } return new XElement[] { - post.thread.board.exportToXml(context, false), + post.thread.board.exportToXml(context, Board.SubboardsOptions.None), post.thread.exportToXml(context), post.exportToXml(context), new XElement("receiver", Account.LoadByUser(post.poster).exportToXml(context)), diff --git a/IISMainHandler/handlers/response/PunishHandler.cs b/IISMainHandler/handlers/response/PunishHandler.cs index a121cd3..5d2dc3d 100644 --- a/IISMainHandler/handlers/response/PunishHandler.cs +++ b/IISMainHandler/handlers/response/PunishHandler.cs @@ -25,13 +25,17 @@ namespace FLocal.IISHandler.handlers.response { if(context.account.user.id == post.poster.id) throw new FLocalException("You cannot punish your own posts"); return new XElement[] { - post.thread.board.exportToXml(context, false), + post.thread.board.exportToXml(context, Board.SubboardsOptions.None), post.thread.exportToXml(context), post.exportToXml(context), post.latestRevision.exportToXml(context), new XElement("layers", from layer in PostLayer.allLayers select layer.exportToXml(context) ), + new XElement("categories", + from category in Category.allCategories select + category.exportToXmlForMainPage(context, Board.SubboardsOptions.AllLevels) + ), new XElement("punishmentTypes", from punishmentType in PunishmentType.allTypes select punishmentType.exportToXml(context) ) diff --git a/IISMainHandler/handlers/response/ReplyHandler.cs b/IISMainHandler/handlers/response/ReplyHandler.cs index 22ca3c8..ddd13b8 100644 --- a/IISMainHandler/handlers/response/ReplyHandler.cs +++ b/IISMainHandler/handlers/response/ReplyHandler.cs @@ -31,7 +31,7 @@ namespace FLocal.IISHandler.handlers.response { } return new XElement[] { - post.thread.board.exportToXml(context, false), + post.thread.board.exportToXml(context, Board.SubboardsOptions.None), post.thread.exportToXml(context), post.exportToXml(context), new XElement("layers", diff --git a/templates/Full/PostPunish.xslt b/templates/Full/PostPunish.xslt index d04a3e7..40574e2 100644 --- a/templates/Full/PostPunish.xslt +++ b/templates/Full/PostPunish.xslt @@ -31,6 +31,19 @@ Тип:

+ + + + + +

Комментарий:
@@ -52,7 +65,7 @@ @@ -96,4 +109,26 @@
+ + + + + + + + + + + + + +    + + + + \ No newline at end of file diff --git a/templates/Full/elems/BoardInfo.xslt b/templates/Full/elems/BoardInfo.xslt index f559d5f..ebe4162 100644 --- a/templates/Full/elems/BoardInfo.xslt +++ b/templates/Full/elems/BoardInfo.xslt @@ -53,12 +53,14 @@ -
- - /Thread//p/ - от - - + +
+ + /Thread//p/ + от + + +
diff --git a/templates/Full/elems/PostInfo.xslt b/templates/Full/elems/PostInfo.xslt index 048797f..c5d79f9 100644 --- a/templates/Full/elems/PostInfo.xslt +++ b/templates/Full/elems/PostInfo.xslt @@ -187,6 +187,37 @@ )
+ + + + Подветка была перенесена + + + Сообщение было перенесено + + + + из обсуждения сообщения + + + /Post/ + + / + + + + + из раздела + + + /Board/ + + / + + + +
+

- Ответ на сообщение + Модерирование сообщения