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.Common; using FLocal.Common.actions; namespace FLocal.Common.dataobjects { public class Post : SqlObject { public class TableSpec : ISqlObjectTableSpec { public const string TABLE = "Posts"; public const string FIELD_ID = "Id"; public const string FIELD_POSTERID = "PosterId"; public const string FIELD_POSTDATE = "PostDate"; public const string FIELD_LASTCHANGEDATE = "LastChangeDate"; public const string FIELD_REVISION = "Revision"; public const string FIELD_LAYERID = "LayerId"; public const string FIELD_TITLE = "Title"; public const string FIELD_BODY = "Body"; public const string FIELD_THREADID = "ThreadId"; public const string FIELD_PARENTPOSTID = "ParentPostId"; 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); } } public class RevisionTableSpec : ISqlObjectTableSpec { public const string TABLE = "Revisions"; public const string FIELD_ID = "Id"; public const string FIELD_POSTID = "PostId"; public const string FIELD_CHANGEDATE = "ChangeDate"; public const string FIELD_TITLE = "Title"; public const string FIELD_BODY = "Body"; public const string FIELD_NUMBER = "Number"; public static readonly RevisionTableSpec instance = new RevisionTableSpec(); public string name { get { return TABLE; } } public string idName { get { return FIELD_ID; } } public void refreshSqlObject(int id) { } } protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } private int _posterId; public int posterId { get { this.LoadIfNotLoaded(); return this._posterId; } } public User poster { get { this.LoadIfNotLoaded(); return User.LoadById(this.posterId); } } private DateTime _postDate; public DateTime postDate { get { this.LoadIfNotLoaded(); return this._postDate; } } private DateTime? _lastChangeDate; public DateTime? lastChangeDate { get { this.LoadIfNotLoaded(); return this._lastChangeDate; } } private int _revision; public int revision { get { this.LoadIfNotLoaded(); return this._revision; } } private int _layerId; public int layerId { get { this.LoadIfNotLoaded(); return this._layerId; } } private string _title; public string title { get { this.LoadIfNotLoaded(); return this._title; } } private string _body; public string body { get { this.LoadIfNotLoaded(); return this._body; } } public string bodyShort { get { return this.body.Replace("
", Util.EOL).Substring(0, Math.Min(1000, this.body.IndexOf("<"))); } } private int _threadId; public int threadId { get { this.LoadIfNotLoaded(); return this._threadId; } } public Thread thread { get { return Thread.LoadById(this.threadId); } } private int? _parentPostId; public int? parentPostId { get { this.LoadIfNotLoaded(); return this._parentPostId; } } public Post parentPost { get { return Post.LoadById(this.parentPostId.Value); } } protected override void doFromHash(Dictionary data) { this._posterId = int.Parse(data[TableSpec.FIELD_POSTERID]); this._postDate = new DateTime(long.Parse(data[TableSpec.FIELD_POSTDATE])); this._lastChangeDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_LASTCHANGEDATE]); this._revision = int.Parse(data[TableSpec.FIELD_REVISION]); this._layerId = int.Parse(data[TableSpec.FIELD_LAYERID]); this._title = data[TableSpec.FIELD_TITLE]; this._body = data[TableSpec.FIELD_BODY]; this._threadId = int.Parse(data[TableSpec.FIELD_THREADID]); this._parentPostId = Util.ParseInt(data[TableSpec.FIELD_PARENTPOSTID]); } public XElement exportToXmlSimpleWithParent(UserContext context) { return new XElement("post", new XElement("id", this.id), new XElement("name", this.title), new XElement("parent", this.thread.exportToXmlSimpleWithParent(context)) ); } public XElement exportToXmlWithoutThread(UserContext context, bool includeParentPost, params XElement[] additional) { XElement result = new XElement("post", new XElement("id", this.id), new XElement("poster", this.poster.exportToXmlForViewing(context)), new XElement("postDate", this.postDate.ToXml()), new XElement("lastChangeDate", this.postDate.ToXml()), new XElement("revision", this.revision), new XElement("layerId", this.layerId), new XElement("title", this.title), new XElement("body", context.outputParams.preprocessBodyIntermediate(this.body)), new XElement("bodyShort", this.bodyShort), new XElement("threadId", this.threadId) ); if(includeParentPost) { if(this.parentPostId.HasValue) { result.Add(new XElement("parentPost", this.parentPost.exportToXmlWithoutThread(context, false))); } } if(additional.Length > 0) { result.Add(additional); } return result; } public Post Reply(User poster, string title, string body, int desiredLayerId) { if(this.thread.isLocked) { throw new FLocalException("thread locked"); } int actualLayerId = Math.Max(poster.getMinAllowedLayer(this.thread.board), desiredLayerId); AbstractChange postInsert = new InsertChange( TableSpec.instance, new Dictionary { { TableSpec.FIELD_THREADID, new ScalarFieldValue(this.thread.id.ToString()) }, { TableSpec.FIELD_PARENTPOSTID, new ScalarFieldValue(this.id.ToString()) }, { TableSpec.FIELD_POSTERID, new ScalarFieldValue(poster.id.ToString()) }, { TableSpec.FIELD_POSTDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, { TableSpec.FIELD_REVISION, new ScalarFieldValue("0") }, { TableSpec.FIELD_LASTCHANGEDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, { TableSpec.FIELD_LAYERID, new ScalarFieldValue(layerId.ToString()) }, { TableSpec.FIELD_TITLE, new ScalarFieldValue(title) }, { TableSpec.FIELD_BODY, new ScalarFieldValue(UBBParser.UBBToIntermediate(body)) }, } ); AbstractChange revisionInsert = new InsertChange( RevisionTableSpec.instance, new Dictionary { { RevisionTableSpec.FIELD_POSTID, new ReferenceFieldValue(postInsert) }, { RevisionTableSpec.FIELD_NUMBER, new ScalarFieldValue("0") }, { RevisionTableSpec.FIELD_CHANGEDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, { RevisionTableSpec.FIELD_TITLE, new ScalarFieldValue(title) }, { RevisionTableSpec.FIELD_BODY, new ScalarFieldValue(body) }, } ); AbstractChange threadUpdate = new UpdateChange( Thread.TableSpec.instance, new Dictionary { { Thread.TableSpec.FIELD_LASTPOSTDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, { Thread.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue() }, { Thread.TableSpec.FIELD_LASTPOSTID, new TwoWayReferenceFieldValue( postInsert, (oldStringId, newStringId) => { int oldId = int.Parse(oldStringId); int newId = int.Parse(newStringId); return Math.Max(oldId, newId).ToString(); } ) } }, this.thread.id ); AbstractChange userUpdate = new UpdateChange( User.TableSpec.instance, new Dictionary { { User.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue() }, }, poster.id ); List changes = new List { postInsert, revisionInsert, threadUpdate, userUpdate, }; int? boardId = thread.boardId; do { Board board = Board.LoadById(boardId.Value); changes.Add( new UpdateChange( Board.TableSpec.instance, new Dictionary { { Board.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue() }, { Board.TableSpec.FIELD_LASTPOSTID, new TwoWayReferenceFieldValue( postInsert, (oldStringId, newStringId) => { int oldId = int.Parse(oldStringId); int newId = int.Parse(newStringId); return Math.Max(oldId, newId).ToString(); } ) } }, board.id ) ); boardId = board.parentBoardId; } while(boardId.HasValue); ChangeSetUtil.ApplyChanges(changes.ToArray()); return Post.LoadById(postInsert.getId().Value); } } }