using System; using System.Configuration; using System.Configuration.Provider; using Npgsql; using System.Collections.Generic; using Yavsc.Model.Blogs; using Yavsc.Model.Circles; using System.Web.Mvc; using NpgsqlTypes; namespace Npgsql.Web.Blog { /// /// Npgsql blog provider. /// public class NpgsqlBlogProvider : BlogProvider { string applicationName; string connectionString; #region implemented abstract members of BlogProvider /// /// Tag the specified postid and tag. /// /// Postid. /// Tag. public override long Tag (long postid, string tag) { using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "insert into bltag (blid,tag) values (@postid,@tag) returning _id"; cmd.Parameters.AddWithValue("@tag",tag); cmd.Parameters.AddWithValue("@postid",postid); cnx.Open (); return (long) cmd.ExecuteScalar (); } } /// /// Removes the tag. /// /// Tagid. public override void RemoveTag (long tagid) { using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "delete from bltag where _id = @tagid"; cmd.Parameters.AddWithValue("@tagid",tagid); cnx.Open (); cmd.ExecuteNonQuery (); } } /// /// Gets the comments. /// /// The comments. /// Postid. /// If set to true get hidden. public override Comment[] GetComments (long postid, bool getHidden) { List cmts = new List (); using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { cmd.CommandText = "select _id, username, bcontent, modified, posted, visible from comment " + "where applicationname = @appname and postid = @id" + ((getHidden) ? " and visible = true ":" ") + "order by posted asc" ; cmd.Parameters.AddWithValue ("@appname", applicationName); cmd.Parameters.AddWithValue ("@id", postid); cnx.Open (); using (NpgsqlDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read ()) { Comment c = new Comment(); c.CommentText = rdr.GetString (rdr.GetOrdinal ("bcontent")); c.From = rdr.GetString (rdr.GetOrdinal ("username")); c.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); c.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); c.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); c.PostId = postid; c.Id = rdr.GetInt64(rdr.GetOrdinal("_id")); cmts.Add (c); } } } return cmts.ToArray(); } /// /// Updates the post. /// /// Postid. /// Title. /// Content. /// If set to true visible. /// Circle identifiers public override void UpdatePost (long postid, string title, string content, bool visible, long [] cids) { using (NpgsqlConnection cnx = new NpgsqlConnection(connectionString)) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) { DateTime now = DateTime.Now; cmd.CommandText = "update blog set modified=@now," + " title = @title," + " bcontent=@content, " + " visible = @visible " + "where _id = @id"; cmd.Parameters.AddWithValue ("@now", now); cmd.Parameters.AddWithValue ("@title", title); cmd.Parameters.AddWithValue ("@content", content); cmd.Parameters.AddWithValue ("@visible", visible); cmd.Parameters.AddWithValue ("@id", postid); cnx.Open (); cmd.ExecuteNonQuery (); } cnx.Close(); } UpdatePostCircles (postid, cids); } /// /// Removes the post. /// /// Postid. public override void RemovePost (long postid) { using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "delete from blog where _id = @id"; cmd.Parameters.AddWithValue ("id", postid); cnx.Open (); cmd.ExecuteNonQuery(); } } /// /// Comment the specified from, postid and content. /// /// From. /// Postid. /// Content. public override long Comment (string from, long postid, string content) { if (from == null) throw new ArgumentNullException("from"); if (content == null) throw new ArgumentNullException("content"); bool visible = AutoValidatesComments; using (NpgsqlConnection cnx= new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { cmd.CommandText = "insert into comment (postid,bcontent," + "modified,posted,visible,username,applicationname)" + "values (@postid,@bcontent,@modified,@posted," + "@visible,@username,@appname) returning _id"; cmd.Parameters.AddWithValue ("@postid", postid); cmd.Parameters.AddWithValue ("@bcontent", content); DateTime now = DateTime.Now; cmd.Parameters.AddWithValue ("@modified", now); cmd.Parameters.AddWithValue ("@posted", now); cmd.Parameters.AddWithValue ("@visible", visible); cmd.Parameters.AddWithValue ("@username", from); cmd.Parameters.AddWithValue ("@appname", applicationName); cnx.Open (); return (long) cmd.ExecuteScalar(); } } /// /// Validates the comment. /// /// Cmtid. public override void ValidateComment (long cmtid) { throw new NotImplementedException (); } /// /// Updates the comment. /// /// Cmtid. /// Content. /// If set to true visible. public override void UpdateComment (long cmtid, string content, bool visible) { throw new NotImplementedException (); } private bool autoValidateComment = true; /// /// Gets or sets a value indicating whether this auto validate comment. /// /// true if auto validate comment; otherwise, false. public override bool AutoValidatesComments { get { return autoValidateComment; } set { autoValidateComment=value; } } /// /// Blogs the title. /// /// The title. /// Username. public override string BlogTitle (string username) { throw new NotImplementedException (); } #endregion /// /// Initialize the specified name and config. /// /// Name. /// Config. public override void Initialize (string name, System.Collections.Specialized.NameValueCollection config) { string cnxName = config ["connectionStringName"]; connectionString = ConfigurationManager.ConnectionStrings [cnxName].ConnectionString; config.Remove ("connectionStringName"); applicationName = config ["applicationName"]; config.Remove ("applicationName"); defaultPageSize = int.Parse ( config ["pageLen"] ?? "10") ; base.Initialize (name, config); } #region implemented abstract members of BlogProvider /// /// Gets the post. /// /// The post. /// Postid. public override BlogEntry GetPost (long postid) { BlogEntry be = null; using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { cmd.CommandText = "select username, title, bcontent, modified, posted, visible, photo from blog " + "where applicationname = @appname and _id = @id"; cmd.Parameters.AddWithValue ("@appname", applicationName); cmd.Parameters.AddWithValue ("@id", postid); cnx.Open (); using (NpgsqlDataReader rdr = cmd.ExecuteReader()) { if (rdr.Read ()) { be = new BlogEntry (); be.Title = rdr.GetString (rdr.GetOrdinal ("title")); be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); be.Author = rdr.GetString (rdr.GetOrdinal ("username")); be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); int oph = rdr.GetOrdinal ("photo"); if (!rdr.IsDBNull(oph)) be.Photo = rdr.GetString (oph); be.Id = postid; } } } if (be!=null) SetCirclesOn (be); return be; } /// /// Removes the comment. /// /// The comment. /// Cmtid. public override long RemoveComment (long cmtid) { long postid = 0; using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "delete from comment where _id = @id returning postid"; cmd.Parameters.AddWithValue ("id", cmtid); cnx.Open (); postid = (long) cmd.ExecuteScalar (); } return postid; } /// /// Gets the post. /// /// The post. /// Username. /// Title. public override UUTBlogEntryCollection GetPost (string username, string title) { UUTBlogEntryCollection bec = new UUTBlogEntryCollection (username,title); using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "select _id,bcontent,modified,posted,visible,photo from blog " + "where applicationname = :appname and username = :username and title = :title"; cmd.Parameters.AddWithValue ("appname", NpgsqlDbType.Varchar, applicationName); cmd.Parameters.AddWithValue ("username", NpgsqlDbType.Varchar ,username); cmd.Parameters.AddWithValue ("title", NpgsqlDbType.Varchar, title); cnx.Open (); cmd.Prepare (); using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) { while (rdr.Read ()) { BlogEntry be = new BlogEntry (); be.Title = title; be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); be.Author = username; be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); { int oph = rdr.GetOrdinal ("photo"); if (!rdr.IsDBNull (oph)) be.Photo = rdr.GetString (oph); } bec.Add (be); } rdr.Close (); } } if (bec.Count != 0) { using (NpgsqlCommand cmdtags = cnx.CreateCommand ()) { long pid = 0; cmdtags.CommandText = "select tag.name from tag,tagged where tag._id = tagged.tagid and tagged.postid = :postid"; cmdtags.Parameters.AddWithValue ("postid", NpgsqlTypes.NpgsqlDbType.Bigint, pid); cmdtags.Prepare (); foreach (BlogEntry be in bec) { List tags = new List (); cmdtags.Parameters ["postid"].Value = be.Id; using (NpgsqlDataReader rdrt = cmdtags.ExecuteReader ()) { while (rdrt.Read ()) { tags.Add (rdrt.GetString (0)); } } be.Tags = tags.ToArray (); } } SetCirclesOn (bec); } } return bec; } private void SetCirclesOn(BlogEntry be) { List circles = new List (); using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmdcircles = cnx.CreateCommand ()) { cmdcircles.CommandText = "select a.circle_id from blog_access a " + "where a.post_id = :pid"; cmdcircles.Parameters.AddWithValue ("pid", be.Id); cnx.Open (); using (NpgsqlDataReader rdr = cmdcircles.ExecuteReader ()) { while (rdr.Read ()) { circles.Add (rdr.GetInt64 (0)); } } } be.AllowedCircles = circles.ToArray (); } private void SetCirclesOn(BlogEntryCollection bec) { foreach (BlogEntry be in bec) { SetCirclesOn (be); } } /// /// Post the specified username, title, content and visible. /// /// Username. /// Title. /// Content. /// If set to true visible. /// . public override long Post (string username, string title, string content, bool visible, long [] circles) { long pid = 0; if (username == null) throw new ArgumentNullException("username"); if (title == null) throw new ArgumentNullException("title"); if (content == null) throw new ArgumentNullException("content"); using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "insert into blog (title,bcontent,modified,posted,visible,username,applicationname)" + "values (:title,:bcontent,:modified,:posted,:visible,:username,:appname) returning _id"; cmd.Parameters.AddWithValue ("title", title); cmd.Parameters.AddWithValue ("bcontent", content); DateTime now = DateTime.Now; cmd.Parameters.AddWithValue ("modified", now); cmd.Parameters.AddWithValue ("posted", now); cmd.Parameters.AddWithValue ("visible", visible); cmd.Parameters.AddWithValue ("username", username); cmd.Parameters.AddWithValue ("appname", applicationName); cnx.Open (); pid = (long)cmd.ExecuteScalar (); } cnx.Close (); } UpdatePostCircles (pid, circles); return pid; } /// /// Updates the post photo. /// /// Pid. /// Photo. public override void UpdatePostPhoto ( long pid, string photo) { using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { cnx.Open (); using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "update blog set photo = :photo where _id = :pid"; cmd.Parameters.AddWithValue ("pid", pid); cmd.Parameters.AddWithValue ("photo", photo); cmd.ExecuteNonQuery (); } cnx.Close (); } } private void UpdatePostCircles( long pid, long[] circles) { using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { cnx.Open (); using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "delete from blog_access where post_id = :pid"; cmd.Parameters.AddWithValue ("pid", pid); cmd.ExecuteNonQuery (); } if (circles!=null) if (circles.Length>0) using (NpgsqlCommand cmd = cnx.CreateCommand ()) { cmd.CommandText = "insert into blog_access (post_id,circle_id) values (:pid,:cid)"; cmd.Parameters.AddWithValue ("pid", pid); cmd.Parameters.Add ("cid", NpgsqlTypes.NpgsqlDbType.Bigint); cmd.Prepare (); foreach (long ci in circles) { cmd.Parameters ["cid"].Value = ci; cmd.ExecuteNonQuery (); } } cnx.Close (); } } /// /// Finds the post. /// /// The post. /// Reader's Name. /// Pattern. /// Searchflags. /// Page index. /// Page size. /// Total records. public override BlogEntryCollection FindPost (string readersName, string pattern, FindBlogEntryFlags searchflags, int pageIndex, int pageSize, out int totalRecords) { BlogEntryCollection c = new BlogEntryCollection (); totalRecords = 0; using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { if (readersName != null) { cmd.CommandText = "select _id, title,bcontent, modified," + "posted,username,visible " + "from blog b left outer join " + "(select count(*)>0 acc, a.post_id pid " + "from blog_access a," + " circle_members m, users u where m.circle_id = a.circle_id " + " and m.member = u.username and u.username = :uname " + " and u.applicationname = :appname " + " group by a.post_id) ma on (ma.pid = b._id) " + "where ( ((ma.acc IS NULL or ma.acc = TRUE) and b.Visible IS TRUE ) or b.username = :uname) "; cmd.Parameters.AddWithValue ("uname", readersName); } else { cmd.CommandText = "select _id, title,bcontent,modified," + "posted,username,visible " + "from blog b left outer join " + "(select count(*)>0 acc, a.post_id pid " + "from blog_access a" + " group by a.post_id) ma on (ma.pid = b._id)" + " where " + " ma.acc IS NULL and " + " b.Visible IS TRUE and " + " applicationname = :appname"; } cmd.Parameters.AddWithValue ("@appname", applicationName); if ((searchflags & FindBlogEntryFlags.MatchContent) > 0) { cmd.CommandText += " and bcontent like :bcontent"; cmd.Parameters.AddWithValue (":bcontent", pattern); } if ((searchflags & FindBlogEntryFlags.MatchTitle) > 0) { cmd.CommandText += " and title like :title"; cmd.Parameters.AddWithValue (":title", pattern); } if ((searchflags & FindBlogEntryFlags.MatchUserName) > 0) { cmd.CommandText += " and username like :username"; cmd.Parameters.AddWithValue (":username", pattern); } if ((searchflags & FindBlogEntryFlags.MatchInvisible) == 0) { cmd.CommandText += " and visible = true"; } cmd.CommandText += " order by posted desc"; cnx.Open (); using (NpgsqlDataReader rdr = cmd.ExecuteReader()) { // pageIndex became one based int firstrec = pageIndex * pageSize; int lastrec = firstrec + pageSize - 1; while (rdr.Read()) { if (totalRecords >= firstrec && totalRecords <= lastrec) { BlogEntry be = new BlogEntry (); be.Title = rdr.GetString (rdr.GetOrdinal ("title")); be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); be.Author = rdr.GetString (rdr.GetOrdinal ("username")); be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); c.Add (be); } totalRecords++; } rdr.Close (); } } foreach (BlogEntry be in c) SetCirclesOn (be); return c; } /// /// Removes the post. /// /// Username. /// Title. public override void RemoveTitle (string username, string title) { using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { cmd.CommandText = "delete from blog where username = @username and applicationname = @appname and title=@title"; cmd.Parameters.AddWithValue ("@username",username); cmd.Parameters.AddWithValue ("@appname", applicationName); cmd.Parameters.AddWithValue ("@title",title); cnx.Open (); cmd.ExecuteNonQuery (); cnx.Close(); } } int defaultPageSize = 10; /// /// Lasts the posts. /// /// The posts. /// Page index. /// Page size. /// Total records. public override BlogEntryCollection LastPosts(int pageIndex, int pageSize, out int totalRecords) { BlogEntryCollection c = new BlogEntryCollection (); using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { /*cmd.CommandText = "select blog.* from blog, " + "(select max(posted) lpost, username " + "from blog where applicationname = @appname " + "group by username) as lblog " + "where blog.posted = lblog.lpost and blog.username = lblog.username " ; */ cmd.CommandText = "select * " + "from blog where applicationname = :appname and visible = true " + " order by posted desc limit :len" ; cmd.Parameters.AddWithValue ("appname", applicationName); cmd.Parameters.AddWithValue ("len", defaultPageSize*10); cnx.Open (); using (NpgsqlDataReader rdr = cmd.ExecuteReader()) { totalRecords = 0; int firstrec = pageIndex * pageSize; int lastrec = firstrec + pageSize - 1; while (rdr.Read()) { if (totalRecords >= firstrec && totalRecords <= lastrec) { BlogEntry be = new BlogEntry (); be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); be.Title = rdr.GetString (rdr.GetOrdinal ("title")); be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); be.Author = rdr.GetString (rdr.GetOrdinal ("username")); be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); be.Visible = true; // because of sql code used c.Add (be); } totalRecords++; } } } foreach (BlogEntry be in c) SetCirclesOn (be); return c; } #endregion } }