Posts transfer implemented; some useful methods in util; Board.exportToXml refactored

main
Inga 🏳‍🌈 14 years ago
parent 524231adc8
commit a9e0690fb3
  1. 2
      Builder/IISMainHandler/build.txt
  2. 1
      Common/Common.csproj
  3. 5
      Common/TableManager.cs
  4. 1
      Common/actions/ChangeSet.cs
  5. 17
      Common/actions/IncrementFieldValue.cs
  6. 31
      Common/dataobjects/Board.cs
  7. 4
      Common/dataobjects/Category.cs
  8. 178
      Common/dataobjects/Post.cs
  9. 18
      Common/dataobjects/Punishment.cs
  10. 111
      Common/dataobjects/PunishmentTransfer.cs
  11. 8
      Common/dataobjects/Thread.cs
  12. 19
      Core/extensions/Extensions.cs
  13. 2
      IISMainHandler/handlers/BoardHandler.cs
  14. 2
      IISMainHandler/handlers/BoardsHandler.cs
  15. 2
      IISMainHandler/handlers/request/CreateThreadHandler.cs
  16. 2
      IISMainHandler/handlers/request/EditHandler.cs
  17. 9
      IISMainHandler/handlers/request/PunishHandler.cs
  18. 2
      IISMainHandler/handlers/request/ReplyHandler.cs
  19. 2
      IISMainHandler/handlers/response/BoardAsThread.cs
  20. 2
      IISMainHandler/handlers/response/CreateThreadHandler.cs
  21. 2
      IISMainHandler/handlers/response/EditHandler.cs
  22. 2
      IISMainHandler/handlers/response/PMReplyToPostHandler.cs
  23. 6
      IISMainHandler/handlers/response/PunishHandler.cs
  24. 2
      IISMainHandler/handlers/response/ReplyHandler.cs
  25. 37
      templates/Full/PostPunish.xslt
  26. 2
      templates/Full/elems/BoardInfo.xslt
  27. 31
      templates/Full/elems/PostInfo.xslt

@ -100,6 +100,7 @@
<Compile Include="dataobjects\Post.cs" /> <Compile Include="dataobjects\Post.cs" />
<Compile Include="dataobjects\PostLayer.cs" /> <Compile Include="dataobjects\PostLayer.cs" />
<Compile Include="dataobjects\Punishment.cs" /> <Compile Include="dataobjects\Punishment.cs" />
<Compile Include="dataobjects\PunishmentTransfer.cs" />
<Compile Include="dataobjects\PunishmentType.cs" /> <Compile Include="dataobjects\PunishmentType.cs" />
<Compile Include="dataobjects\QuickLink.cs" /> <Compile Include="dataobjects\QuickLink.cs" />
<Compile Include="dataobjects\Revision.cs" /> <Compile Include="dataobjects\Revision.cs" />

@ -18,11 +18,12 @@ namespace FLocal.Common {
dataobjects.Moderator.TableSpec.instance, dataobjects.Moderator.TableSpec.instance,
dataobjects.PMConversation.TableSpec.instance, dataobjects.PMConversation.TableSpec.instance,
dataobjects.PMMessage.TableSpec.instance, dataobjects.PMMessage.TableSpec.instance,
dataobjects.Punishment.TableSpec.instance,
dataobjects.PunishmentType.TableSpec.instance,
dataobjects.Poll.TableSpec.instance, dataobjects.Poll.TableSpec.instance,
dataobjects.Post.TableSpec.instance, dataobjects.Post.TableSpec.instance,
dataobjects.PostLayer.TableSpec.instance, dataobjects.PostLayer.TableSpec.instance,
dataobjects.Punishment.TableSpec.instance,
dataobjects.PunishmentTransfer.TableSpec.instance,
dataobjects.PunishmentType.TableSpec.instance,
dataobjects.QuickLink.TableSpec.instance, dataobjects.QuickLink.TableSpec.instance,
dataobjects.Revision.TableSpec.instance, dataobjects.Revision.TableSpec.instance,
dataobjects.Session.TableSpec.instance, dataobjects.Session.TableSpec.instance,

@ -36,6 +36,7 @@ namespace FLocal.Common.actions {
dataobjects.Invite.TableSpec.TABLE, dataobjects.Invite.TableSpec.TABLE,
dataobjects.Moderator.TableSpec.TABLE, dataobjects.Moderator.TableSpec.TABLE,
dataobjects.Punishment.TableSpec.TABLE, dataobjects.Punishment.TableSpec.TABLE,
dataobjects.PunishmentTransfer.TableSpec.TABLE,
dataobjects.Session.TableSpec.TABLE, dataobjects.Session.TableSpec.TABLE,
} }
); );

@ -6,8 +6,21 @@ using System.Text;
namespace FLocal.Common.actions { namespace FLocal.Common.actions {
class IncrementFieldValue : AbstractFieldValue { class IncrementFieldValue : AbstractFieldValue {
public static readonly Func<string, string> INCREMENTOR = s => (int.Parse(s)+1).ToString(); public static Func<string, string> INCREMENTOR_CUSTOM(int i) {
public static readonly Func<string, string> DECREMENTOR = s => (int.Parse(s)-1).ToString(); return s => (int.Parse(s)+i).ToString();
}
public static Func<string, string> 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<string, string> GREATEST(int val) { public static Func<string, string> GREATEST(int val) {
return s => { return s => {

@ -11,6 +11,13 @@ using FLocal.Common.actions;
namespace FLocal.Common.dataobjects { namespace FLocal.Common.dataobjects {
public class Board : SqlObject<Board> { public class Board : SqlObject<Board> {
[Flags]
public enum SubboardsOptions {
None = 0x0,
FirstLevel = 0x1,
AllLevels = 0x3
}
public class TableSpec : IComplexSqlObjectTableSpec { public class TableSpec : IComplexSqlObjectTableSpec {
public const string TABLE = "Boards"; public const string TABLE = "Boards";
public const string FIELD_ID = "Id"; 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", XElement result = new XElement("board",
new XElement("id", this.id), new XElement("id", this.id),
new XElement("sortOrder", this.sortOrder), new XElement("sortOrder", this.sortOrder),
@ -226,9 +233,9 @@ namespace FLocal.Common.dataobjects {
result.Add(new XElement("hasNewPosts", this.hasNewPosts(context.account).ToPlainString())); result.Add(new XElement("hasNewPosts", this.hasNewPosts(context.account).ToPlainString()));
} }
if(includeSubBoards) { if((subboardsOptions & SubboardsOptions.FirstLevel) == SubboardsOptions.FirstLevel) {
result.Add(new XElement("subBoards", 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); 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<Board> boardAndParents {
get {
return this.ToSequence(board => board.parentBoardId.HasValue ? new Board[] { board.parentBoard } : new Board[0]);
}
}
} }
} }

@ -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", return new XElement("category",
new XElement("id", this.id), new XElement("id", this.id),
new XElement("name", this.name), new XElement("name", this.name),
new XElement("sortOrder", this.sortOrder), 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))
); );
} }

@ -281,10 +281,15 @@ namespace FLocal.Common.dataobjects {
PostLayer actualLayer = poster.getActualLayer(this.thread.board, desiredLayer); PostLayer actualLayer = poster.getActualLayer(this.thread.board, desiredLayer);
Post newPost;
lock(this.thread.locker) {
var changes = Thread.getNewPostChanges(this.thread.board, this.threadId, this, poster, actualLayer, title, body, date, forcedPostId); var changes = Thread.getNewPostChanges(this.thread.board, this.threadId, this, poster, actualLayer, title, body, date, forcedPostId);
ChangeSetUtil.ApplyChanges(changes.Value.ToArray()); ChangeSetUtil.ApplyChanges(changes.Value.ToArray());
return Post.LoadById(changes.Key.getId().Value); newPost = Post.LoadById(changes.Key.getId().Value);
}
return newPost;
} }
private readonly object Edit_locker = new object(); //TODO: move locking to DB private readonly object Edit_locker = new object(); //TODO: move locking to DB
@ -335,8 +340,24 @@ namespace FLocal.Common.dataobjects {
} }
} }
private IEnumerable<Post> 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(); 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); if(!Moderator.isModerator(account, this.thread.board)) throw new FLocalException(account.id + " is not a moderator in board " + this.thread.board.id);
@ -344,7 +365,9 @@ namespace FLocal.Common.dataobjects {
lock(this.Punish_Locker) { lock(this.Punish_Locker) {
List<AbstractChange> changes = ( lock(this.thread.locker) {
IEnumerable<AbstractChange> changes = (
from punishment in this.punishments from punishment in this.punishments
select (AbstractChange)new UpdateChange( select (AbstractChange)new UpdateChange(
Punishment.TableSpec.instance, Punishment.TableSpec.instance,
@ -353,19 +376,157 @@ namespace FLocal.Common.dataobjects {
}, },
punishment.id punishment.id
) )
).ToList(); );
changes.Add( 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( new UpdateChange(
Thread.TableSpec.instance,
new Dictionary<string,AbstractFieldValue> {
{ Thread.TableSpec.FIELD_BOARDID, new ScalarFieldValue(_transferInfo.newBoardId.ToString()) },
},
this.thread.id
)
);
}
} else {
List<Post> postsAffected;
if(_transferInfo.isSubthreadTransfer) {
postsAffected = this.ToSequence(post => post.subPosts).OrderBy(post => post.id).ToList();
} else {
postsAffected = new List<Post>();
postsAffected.Add(this);
}
lastAffectedPost = postsAffected.Last();
totalAffectedPosts = postsAffected.Count;
InsertChange threadCreate = new InsertChange(
Thread.TableSpec.instance,
new Dictionary<string,AbstractFieldValue> {
{ 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, TableSpec.instance,
new Dictionary<string,AbstractFieldValue> { new Dictionary<string,AbstractFieldValue> {
{ TableSpec.FIELD_TOTALPUNISHMENTS, new IncrementFieldValue() }, { 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<string,AbstractFieldValue> {
{ TableSpec.FIELD_PARENTPOSTID, new ScalarFieldValue(this.parentPostId.ToString()) },
},
post.id
)
);
}
}
changes = changes.Union(
from board in this.thread.board.boardAndParents
select (AbstractChange)new UpdateChange(
Board.TableSpec.instance,
new Dictionary<string,AbstractFieldValue> {
{ 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<string,AbstractFieldValue> {
{ 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<string,AbstractFieldValue> {
{ 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<string,AbstractFieldValue> {
{ TableSpec.FIELD_PARENTPOSTID, new ScalarFieldValue(null) },
}, },
this.id this.id
) )
); );
changes.Add( if(this.parentPostId.HasValue) {
changes = changes.Union(
new UpdateChange(
Thread.TableSpec.instance,
new Dictionary<string,AbstractFieldValue> {
{ Thread.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue(IncrementFieldValue.DECREMENTOR_CUSTOM(totalAffectedPosts)) },
},
this.threadId
)
);
}
}
changes = changes.Union(
new UpdateChange(
TableSpec.instance,
new Dictionary<string,AbstractFieldValue> {
{ TableSpec.FIELD_TOTALPUNISHMENTS, new IncrementFieldValue() },
},
this.id
),
new InsertChange( new InsertChange(
Punishment.TableSpec.instance, Punishment.TableSpec.instance,
new Dictionary<string,AbstractFieldValue> { new Dictionary<string,AbstractFieldValue> {
@ -378,6 +539,7 @@ namespace FLocal.Common.dataobjects {
{ Punishment.TableSpec.FIELD_ISWITHDRAWED, new ScalarFieldValue("0") }, { Punishment.TableSpec.FIELD_ISWITHDRAWED, new ScalarFieldValue("0") },
{ Punishment.TableSpec.FIELD_COMMENT, new ScalarFieldValue(comment) }, { Punishment.TableSpec.FIELD_COMMENT, new ScalarFieldValue(comment) },
{ Punishment.TableSpec.FIELD_EXPIRES, new ScalarFieldValue(DateTime.Now.Add(type.timeSpan).ToUTCString()) }, { 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) },
} }
) )
); );
@ -401,6 +563,8 @@ namespace FLocal.Common.dataobjects {
); );
newMessage.conversation.markAsRead(account, newMessage, newMessage); newMessage.conversation.markAsRead(account, newMessage, newMessage);
} }
}
} }
} }

@ -22,6 +22,7 @@ namespace FLocal.Common.dataobjects {
public const string FIELD_ISWITHDRAWED = "IsWithdrawed"; public const string FIELD_ISWITHDRAWED = "IsWithdrawed";
public const string FIELD_COMMENT = "Comment"; public const string FIELD_COMMENT = "Comment";
public const string FIELD_EXPIRES = "Expires"; public const string FIELD_EXPIRES = "Expires";
public const string FIELD_TRANSFERID = "TransferId";
public static readonly TableSpec instance = new TableSpec(); public static readonly TableSpec instance = new TableSpec();
public string name { get { return TABLE; } } public string name { get { return TABLE; } }
public string idName { get { return FIELD_ID; } } 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<string, string> data) { protected override void doFromHash(Dictionary<string, string> data) {
this._postId = int.Parse(data[TableSpec.FIELD_POSTID]); this._postId = int.Parse(data[TableSpec.FIELD_POSTID]);
this._ownerId = int.Parse(data[TableSpec.FIELD_OWNERID]); 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._isWithdrawed = Util.string2bool(data[TableSpec.FIELD_ISWITHDRAWED]);
this._comment = data[TableSpec.FIELD_COMMENT]; this._comment = data[TableSpec.FIELD_COMMENT];
this._expires = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_EXPIRES]).Value; this._expires = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_EXPIRES]).Value;
this._transferId = Util.ParseInt(data[TableSpec.FIELD_TRANSFERID]);
} }
public XElement exportToXml(UserContext context) { public XElement exportToXml(UserContext context) {
@ -149,7 +164,8 @@ namespace FLocal.Common.dataobjects {
this.punishmentType.exportToXml(context), this.punishmentType.exportToXml(context),
new XElement("isWithdrawed", this.isWithdrawed.ToPlainString()), new XElement("isWithdrawed", this.isWithdrawed.ToPlainString()),
new XElement("comment", this.comment), new XElement("comment", this.comment),
new XElement("expires", this.expires) new XElement("expires", this.expires),
this.transferId.HasValue ? this.transfer.exportToXml(context) : null
); );
} }

@ -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<PunishmentTransfer> {
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<string, string> 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())
);
}
}
}

@ -470,6 +470,14 @@ namespace FLocal.Common.dataobjects {
return new KeyValuePair<AbstractChange,IEnumerable<AbstractChange>>(postInsert, changes); return new KeyValuePair<AbstractChange,IEnumerable<AbstractChange>>(postInsert, changes);
} }
public readonly object locker = new object();
public void Synchronized(Action action) {
lock(this.locker) {
this.board.Synchronized(action);
}
}
} }
} }

@ -57,7 +57,7 @@ namespace FLocal.Core {
return string.Join(",", (from elem in list select elem.ToString()).ToArray()); 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"; return val ? "1" : "0";
} }
@ -230,5 +230,22 @@ namespace FLocal.Core {
return date.ToUniversalTime().ToString("u"); return date.ToUniversalTime().ToString("u");
} }
public static IEnumerable<T> ToSequence<T>(this T obj, Func<T, IEnumerable<T>> 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<T>(this List<T> list) {
return list[list.Count-1];
}
public static IEnumerable<T> Union<T>(this IEnumerable<T> enumerable, params T[] second) {
return enumerable.Union((IEnumerable<T>)second);
}
} }
} }

@ -25,7 +25,7 @@ namespace FLocal.IISHandler.handlers {
IEnumerable<Thread> threads = board.getThreads(pageOuter); IEnumerable<Thread> threads = board.getThreads(pageOuter);
XElement[] result = new XElement[] { XElement[] result = new XElement[] {
new XElement("currentLocation", board.exportToXmlSimpleWithParent(context)), 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", new XElement("threads",
from thread in threads select thread.exportToXml(context), from thread in threads select thread.exportToXml(context),
pageOuter.exportToXml(1, 5, 1) pageOuter.exportToXml(1, 5, 1)

@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers {
override protected IEnumerable<XElement> getSpecificData(WebContext context) { override protected IEnumerable<XElement> getSpecificData(WebContext context) {
return new XElement[] { 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("totalRegistered", Config.instance.mainConnection.GetCountByConditions(User.TableSpec.instance, new EmptyCondition())),
new XElement("activity", new XElement("activity",
new XElement("threshold", Config.instance.ActivityThreshold.ToString()), new XElement("threshold", Config.instance.ActivityThreshold.ToString()),

@ -24,7 +24,7 @@ namespace FLocal.IISHandler.handlers.request {
newThread.markAsRead(context.session.account, newPost, newPost); newThread.markAsRead(context.session.account, newPost, newPost);
return new XElement[] { return new XElement[] {
newThread.board.exportToXml(context, false), newThread.board.exportToXml(context, Board.SubboardsOptions.None),
newPost.exportToXml(context) newPost.exportToXml(context)
}; };
} }

@ -26,7 +26,7 @@ namespace FLocal.IISHandler.handlers.request {
); );
return new XElement[] { return new XElement[] {
post.thread.board.exportToXml(context, false), post.thread.board.exportToXml(context, Board.SubboardsOptions.None),
postXml postXml
}; };
} }

@ -21,11 +21,16 @@ namespace FLocal.IISHandler.handlers.request {
post.Punish( post.Punish(
context.session.account, context.session.account,
PunishmentType.LoadById(int.Parse(context.httprequest.Form["punishmentTypeId"])), 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[] { return new XElement[] {
post.thread.board.exportToXml(context, false), post.thread.board.exportToXml(context, Board.SubboardsOptions.None),
postXml postXml
}; };
} }

@ -24,7 +24,7 @@ namespace FLocal.IISHandler.handlers.request {
newPost.thread.markAsRead(context.session.account, newPost, newPost); newPost.thread.markAsRead(context.session.account, newPost, newPost);
return new XElement[] { return new XElement[] {
newPost.thread.board.exportToXml(context, false), newPost.thread.board.exportToXml(context, Board.SubboardsOptions.None),
newPost.exportToXml(context) newPost.exportToXml(context)
}; };
} }

@ -32,7 +32,7 @@ namespace FLocal.IISHandler.handlers.response {
); );
return new XElement[] { return new XElement[] {
new XElement("currentLocation", board.exportToXmlSimpleWithParent(context)), 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", new XElement("posts",
from thread in threads select thread.firstPost.exportToXml( from thread in threads select thread.firstPost.exportToXml(
context, context,

@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers.response {
Board board = Board.LoadById(int.Parse(context.requestParts[1])); Board board = Board.LoadById(int.Parse(context.requestParts[1]));
return new XElement[] { return new XElement[] {
board.exportToXml(context, false), board.exportToXml(context, Board.SubboardsOptions.None),
new XElement("layers", new XElement("layers",
from layer in PostLayer.allLayers select layer.exportToXml(context) from layer in PostLayer.allLayers select layer.exportToXml(context)
), ),

@ -22,7 +22,7 @@ namespace FLocal.IISHandler.handlers.response {
Post post = Post.LoadById(int.Parse(context.requestParts[1])); Post post = Post.LoadById(int.Parse(context.requestParts[1]));
return new XElement[] { return new XElement[] {
post.thread.board.exportToXml(context, false), post.thread.board.exportToXml(context, Board.SubboardsOptions.None),
post.thread.exportToXml(context), post.thread.exportToXml(context),
post.exportToXml(context), post.exportToXml(context),
post.latestRevision.exportToXml(context), post.latestRevision.exportToXml(context),

@ -31,7 +31,7 @@ namespace FLocal.IISHandler.handlers.response {
} }
return new XElement[] { return new XElement[] {
post.thread.board.exportToXml(context, false), post.thread.board.exportToXml(context, Board.SubboardsOptions.None),
post.thread.exportToXml(context), post.thread.exportToXml(context),
post.exportToXml(context), post.exportToXml(context),
new XElement("receiver", Account.LoadByUser(post.poster).exportToXml(context)), new XElement("receiver", Account.LoadByUser(post.poster).exportToXml(context)),

@ -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"); if(context.account.user.id == post.poster.id) throw new FLocalException("You cannot punish your own posts");
return new XElement[] { return new XElement[] {
post.thread.board.exportToXml(context, false), post.thread.board.exportToXml(context, Board.SubboardsOptions.None),
post.thread.exportToXml(context), post.thread.exportToXml(context),
post.exportToXml(context), post.exportToXml(context),
post.latestRevision.exportToXml(context), post.latestRevision.exportToXml(context),
new XElement("layers", new XElement("layers",
from layer in PostLayer.allLayers select layer.exportToXml(context) 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", new XElement("punishmentTypes",
from punishmentType in PunishmentType.allTypes select punishmentType.exportToXml(context) from punishmentType in PunishmentType.allTypes select punishmentType.exportToXml(context)
) )

@ -31,7 +31,7 @@ namespace FLocal.IISHandler.handlers.response {
} }
return new XElement[] { return new XElement[] {
post.thread.board.exportToXml(context, false), post.thread.board.exportToXml(context, Board.SubboardsOptions.None),
post.thread.exportToXml(context), post.thread.exportToXml(context),
post.exportToXml(context), post.exportToXml(context),
new XElement("layers", new XElement("layers",

@ -31,6 +31,19 @@
<xsl:text>Òèï:</xsl:text><br/> <xsl:text>Òèï:</xsl:text><br/>
<xsl:apply-templates select="punishmentTypes/punishmentType"/> <xsl:apply-templates select="punishmentTypes/punishmentType"/>
<br/> <br/>
<input type="checkbox" name="transfer" value="transfer" id="Transfer"/>
<label for="Transfer">
<xsl:text> Ïåðåíåñòè ñîîáùåíèå â ðàçäåë</xsl:text>
</label>
<select name="transfer_boardId">
<option value="-1">Âûáåðèòå ðàçäåë</option>
<xsl:apply-templates select="categories/category" mode="select"/>
</select>
<input type="checkbox" name="transfer_subThread" value="transfer_subThread" id="Transfer_SubThread"/>
<label for="Transfer_SubThread">
<xsl:text> ñî âñåìè îòâåòàìè</xsl:text>
</label>
<br/>
<br/> <br/>
<xsl:text>Êîììåíòàðèé: </xsl:text> <xsl:text>Êîììåíòàðèé: </xsl:text>
<br/> <br/>
@ -52,7 +65,7 @@
<table cellpadding="3" cellspacing="1" width="100%" class="tableborders"> <table cellpadding="3" cellspacing="1" width="100%" class="tableborders">
<tr> <tr>
<td class="tdheader"> <td class="tdheader">
<xsl:text>Ответ на сообщение</xsl:text> <xsl:text>Ìîäåðèðîâàíèå ñîîáùåíèÿ</xsl:text>
</td> </td>
</tr> </tr>
<tr class="darktable"> <tr class="darktable">
@ -96,4 +109,26 @@
<br/> <br/>
</xsl:template> </xsl:template>
<xsl:template match="category" mode="select">
<optgroup>
<xsl:attribute name="label"><xsl:value-of select="name"/></xsl:attribute>
<xsl:apply-templates select="boards/board" mode="select"/>
</optgroup>
</xsl:template>
<xsl:template match="board" mode="select">
<xsl:param name="prefix"/>
<option>
<xsl:attribute name="value"><xsl:value-of select="id"/></xsl:attribute>
<xsl:value-of select="$prefix"/>
<xsl:value-of select="name"/>
</option>
<xsl:apply-templates select="subBoards/board" mode="select">
<xsl:with-param name="prefix">
<xsl:value-of select="$prefix"/>
<xsl:text>&#160;&#160;</xsl:text>
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

@ -53,12 +53,14 @@
</xsl:template> </xsl:template>
<xsl:template match="lastPostInfo"> <xsl:template match="lastPostInfo">
<xsl:if test="post">
<xsl:apply-templates select="post/postDate/date" mode="dateTime"/><br /> <xsl:apply-templates select="post/postDate/date" mode="dateTime"/><br />
<a> <a>
<xsl:attribute name="href">/Thread/<xsl:value-of select="post/threadId"/>/p<xsl:value-of select="post/id"/>/</xsl:attribute> <xsl:attribute name="href">/Thread/<xsl:value-of select="post/threadId"/>/p<xsl:value-of select="post/id"/>/</xsl:attribute>
<xsl:text>îň </xsl:text> <xsl:text>îň </xsl:text>
<xsl:value-of select="post/poster/user/name"/> <xsl:value-of select="post/poster/user/name"/>
</a> </a>
</xsl:if>
</xsl:template> </xsl:template>
<xsl:template match="subBoards/board"> <xsl:template match="subBoards/board">

@ -187,6 +187,37 @@
<xsl:apply-templates select="punishmentDate/date" mode="dateTime"/> <xsl:apply-templates select="punishmentDate/date" mode="dateTime"/>
<xsl:text>)</xsl:text> <xsl:text>)</xsl:text>
<br/> <br/>
<xsl:if test="transfer">
<xsl:choose>
<xsl:when test="transfer/isSubthreadTransfer='true'">
<xsl:text>Ïîäâåòêà áûëà ïåðåíåñåíà</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>Ñîîáùåíèå áûëî ïåðåíåñåíî</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="transfer/oldParentPost">
<xsl:text> èç îáñóæäåíèÿ ñîîáùåíèÿ </xsl:text>
<a>
<xsl:attribute name="href">
<xsl:text>/Post/</xsl:text>
<xsl:value-of select="transfer/oldParentPost/post/id"/>
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:value-of select="transfer/oldParentPost/post/title"/>
</a>
</xsl:if>
<xsl:text> èç ðàçäåëà </xsl:text>
<a>
<xsl:attribute name="href">
<xsl:text>/Board/</xsl:text>
<xsl:value-of select="transfer/oldBoard/board/id"/>
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:value-of select="transfer/oldBoard/board/name"/>
</a>
<br/>
</xsl:if>
<br/> <br/>
</font> </font>
</td> </td>

Loading…
Cancel
Save