Simple CMS with Linq to SQL part II-a

This isn’t a new post per-se, but a few refinements to our existing project, including added comments in the new classes, before proceeding further. I pretty much rushed through to getting content adding, editing deleting functionality so let’s see how much we can smooth the edges before moving on…

First, I added a simple code file called Summaries.cs to the Models folder with the following…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SimpleCMS.Models;

namespace SimpleCMS.Models
{
	public class PageSummary : ContentPage { }

	public class CommentSummary : ContentComment { }
}

All this does is allow us to create an anonymous type wrapper for use in page and content summaries without getting all the associated fields in the object. It’s a performance thing.

Next, the modified PageView class in the Models folder.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SimpleCMS.Helpers;

namespace SimpleCMS.Models
{
    public class PageView
    {
		/// <summary>
		/// Current viewing page
		/// </summary>
		public ContentPage Page { get; set; }

		/// <summary>
		/// Paged index list of pages
		/// </summary>
		public PagedList<ContentPage> Pages { get; set; }

		/// <summary>
		/// Paged index list of pages
		/// </summary>
		public PagedList<PageSummary> PageSummary { get; set; }


		/// <summary>
		/// Paged list of comments in the current page
		/// </summary>
		public PagedList<ContentComment> Comments { get; set; }

		/// <summary>
		/// Paged list of comments in the current page
		/// </summary>
		public PagedList<CommentSummary> CommentSummary { get; set; }

		/// <summary>
		/// This is for breadcrumb navigation use
		/// </summary>
		public Dictionary<int, string> Parents { get; set; }

		/// <summary>
		/// Constructor
		/// </summary>
		public PageView() { }

		/// <summary>
		/// Plain view of a content page
		/// </summary>
		/// <param name="_page">Current content page</param>
		public PageView(ContentPage _page)
		{
			Page = _page;
		}

		/// <summary>
		/// Plain view with comments
		/// </summary>
		/// <param name="_page">Current content page</param>
		/// <param name="_comments">List of commments in the current page</param>
		public PageView(ContentPage _page, PagedList<ContentComment> _comments)
		{
			Page = _page;
			Comments = _comments;
		}

		/// <summary>
		/// If no comments or sub pages are present, then this is an index view
		/// </summary>
		/// <param name="_pages">List of pages in current index</param>
		public PageView(PagedList<ContentPage> _pages)
		{
			Pages = _pages;
		}

		/// <summary>
		/// Full content page view with sub page summaries
		/// </summary>
		/// <param name="_page">Current content page</param>
		/// <param name="_pages">Paged list of sub pages</param>
		/// <param name="_comments">Paged list of comments</param>
		public PageView(ContentPage _page, PagedList<PageSummary> _pages, 
			PagedList<ContentComment> _comments)
		{
			Page = _page;
			PageSummary = _pages;
			Comments = _comments;
		}

		/// <summary>
		/// Full content page view with expanded pages
		/// </summary>
		/// <param name="_page">Current content page</param>
		/// <param name="_pages">Paged list of sub pages</param>
		/// <param name="_comments">Paged list of comments</param>
		public PageView(ContentPage _page, PagedList<ContentPage> _pages, 
			PagedList<ContentComment> _comments)
		{
			Page = _page;
			Pages = _pages;
			Comments = _comments;
		}

		/// <summary>
		/// Checks if this view has a page to display. If not, then 
		/// it's probably a main index.
		/// </summary>
		public bool HasPage {
			get { return (Page != null); }
		}
    }
}

Our new PagesController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SimpleCMS.Models;
using SimpleCMS.Helpers;
using MarkdownSharp;

namespace SimpleCMS.Controllers
{
	public class PagesController : Controller
	{
		/// <summary>
		/// Page index view. Lists the pages under the given parent Id
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <param name="page">Current page index</param>
		/// <returns>Page view</returns>
		public ActionResult Index(int? id, int? page)
		{
			id = id ?? 0;
			page = page ?? 1;

			ContentPage content = new ContentPage();
			PagedList<ContentPage> pages;

			using (SimpleCMSDataContext db = new SimpleCMSDataContext())
			{
				// Get the published pages
				pages = (from p in db.ContentPages
						 where p.ParentId == id.Value
						 orderby p.PubDate descending
						 select p).ToPagedList(page.Value, 10);

				if (id > 0)
				{
					content = (from p in db.ContentPages
							   where p.PageId == id.Value
							   select p).Single();
				}


			}

			PageView index = new PageView(pages);

			if (content.PageId > 0)
				index.Page = content;

			ViewData.Model = index;
			return View();
		}

		/// <summary>
		/// Basically the Details view
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <param name="page">Current page index (for comments)</param>
		/// <returns>Read view or the index if no Id was found</returns>
		public ActionResult Read(int? id, int? page)
		{
			// Page Id
			id = id ?? 0;
			page = page ?? 1;

			if (id.Value > 0)
			{
				ContentPage content;
				PagedList<ContentComment> comments;

				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					content = (from p in db.ContentPages
							   where p.PageId == id.Value
							   select p).Single();

					// Increment view count
					content.ViewCount = Util.DefaultInt(content.ViewCount, 0) + 1;

					comments = (from c in db.ContentComments
								where c.PageId == id.Value
								orderby c.CreatedDate ascending
								select c).ToPagedList(page.Value, 20);

					db.SubmitChanges();
				}

				ViewData.Model = new PageView(content, comments);
				return View();
			}
			return RedirectToAction("Index");
		}

		/// <summary>
		/// Creates a new page under the given parent Id
		/// </summary>
		/// <param name="id">Parent Id</param>
		/// <param name="collection">Form data input</param>
		/// <returns></returns>
		[HttpPost]
		public ActionResult Create(int? id, FormCollection collection)
		{
			// Parent Id
			id = id ?? 0;

			int newpageid = 0;

			ContentPage content;
			using (SimpleCMSDataContext db = new SimpleCMSDataContext())
			{
				// Gets the page data from form
				content = GetPageFromCollection(id.Value, collection, true);

				// Insert the new page
				db.ContentPages.InsertOnSubmit(content);

				if (id.Value > 0)
				{
					// Update parent page count if this page has a parent
					ContentPage parent = (from p in db.ContentPages
										  where p.PageId == id.Value
										  select p).Single();

					parent.PageCount = (from p in db.ContentPages
										where p.ParentId == id
										select p.PageId).Count() + 1;
				}

				// Save the page
				db.SubmitChanges();

				// Store the new Id for redirect
				newpageid = content.PageId;
			}

			// We have an Id
			if (newpageid > 0)
				return RedirectToAction("Read", new { id = newpageid });
			else
				return RedirectToAction("Index");
		}

		/// <summary>
		/// Edits a given page
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <returns>Page edit view or the index if no Id is found</returns>
		public ActionResult Edit(int? id)
		{
			// Page Id
			id = id ?? 0;

			if (id.Value > 0)
			{
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					ContentPage content = (from p in db.ContentPages
										   where p.PageId == id.Value
										   select p).Single();

					ViewData.Model = content;
					return View();
				}
			}
			return RedirectToAction("Index");
		}

		/// <summary>
		/// Edits a given page
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <param name="collection">Form data input</param>
		/// <returns>Page read view</returns>
		[HttpPost]
		public ActionResult Edit(int? id, FormCollection collection)
		{
			// Page Id
			id = id ?? 0;

			if (id.Value > 0)
			{
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					ContentPage content = (from p in db.ContentPages
										   where p.PageId == id.Value
										   select p).Single();

					ContentPage edited = GetPageFromCollection(id.Value, collection, false);

					// Basics
					content.Title = edited.Title;
					content.Description = edited.Description;
					content.AbstractText = edited.AbstractText;
					content.AbstractHtml = edited.AbstractHtml;
					content.BodyHtml = edited.BodyHtml;
					content.BodyText = edited.BodyText;

					//Edited date
					content.LastModified = edited.LastModified;

					// Moderation
					content.Approved = edited.Approved;
					content.AnonComments = edited.AnonComments;
					content.Moderated = edited.Moderated;

					db.SubmitChanges();
				}

				return RedirectToAction("Read", new { id = id });
			}
			return RedirectToAction("Index");
		}

		/// <summary>
		/// Deletes a given page
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <returns>Delete page view or the index if no id is given</returns>
		public ActionResult Delete(int? id)
		{
			// Page Id
			id = id ?? 0;

			if (id.Value > 0)
			{
				ContentPage page;
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					page = (from p in db.ContentPages
							where p.PageId == id.Value
							select p).Single();
				}
				ViewData.Model = page;
				return View();
			}
			return RedirectToAction("Index");
		}

		/// <summary>
		/// Deletes a given page
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <param name="collection">Form data input</param>
		/// <returns>Redirects to the page index</returns>
		[HttpPost]
		public ActionResult Delete(int? id, FormCollection collection)
		{
			id = id ?? 0;
			if (id.Value > 0)
			{
				try
				{
					using (SimpleCMSDataContext db = new SimpleCMSDataContext())
					{
						ContentPage page = (from p in db.ContentPages
											where p.PageId == id
											select p).Single();

						db.ContentPages.DeleteOnSubmit(page);
						db.SubmitChanges();
					}
				}
				catch { }
			}
			return RedirectToAction("Index");
		}


		/// <summary>
		/// Creates a page comment under the given page Id
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <param name="collection">Form input data</param>
		/// <returns>Read page view</returns>
		[HttpPost]
		public ActionResult CreateComment(int? id, FormCollection collection)
		{
			// Page Id
			id = id ?? 0;

			if (id.Value > 0)
			{
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					// Get our page
					ContentPage content = (from p in db.ContentPages
										   where p.PageId == id
										   select p).Single();

					// If comments are enabled
					if (Util.DefaultBool(content.EnableComments, true))
					{
						// Create comment from the form data
						ContentComment comment =
							GetCommentFromCollection(id.Value, collection, true);

						// If the moderation is enabled, we need to 
						// disapprove this post first
						if(Util.DefaultBool(content.Moderated, false))
							comment.Approved = false;

						// Insert the new comment
						db.ContentComments.InsertOnSubmit(comment);

						// Update the comment count
						content.CommentCount = Util.DefaultInt(content.CommentCount, 0) + 1;

						db.SubmitChanges();
					}
				}
			}

			// There was no page or something went wrong
			if (id == 0)
				return RedirectToAction("Index");

			return RedirectToAction("Read", new { id = id.Value });
		}

		/// <summary>
		/// Edits a given comment
		/// </summary>
		/// <param name="id">Comment Id</param>
		/// <returns>Edit view</returns>
		public ActionResult EditComment(int? id)
		{
			// Comment Id
			id = id ?? 0;

			// Stores the page Id
			int pageid = 0;

			if (id.Value > 0)
			{
				ContentComment comment;
				ContentPage contentpage;
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					// Get the comment to be edited
					comment = (from c in db.ContentComments
							   where c.CommentId == id.Value
							   select c).Single();

					// Get the contnt page for this comment 
					// (we need some elements of this to show the comment)
					contentpage = (from p in db.ContentPages
								   where p.PageId == comment.PageId
								   select p).Single();

					// Attach the page to the comment
					comment.ContentPage = contentpage;

					pageid = comment.PageId;

					ViewData.Model = comment;
					return View();
				}
			}

			// There was no page or something went wrong
			if (pageid == 0)
				return RedirectToAction("Index");

			return RedirectToAction("Read", new { id = pageid });
		}


		/// <summary>
		/// Edits a given comment
		/// </summary>
		/// <param name="id">Comment Id</param>
		/// <param name="collection">Form data input</param>
		/// <returns>Page read view</returns>
		[HttpPost]
		public ActionResult EditComment(int? id, FormCollection collection)
		{
			// Comment Id
			id = id ?? 0;

			// Stores the page Id
			int pageid = 0;

			if (id.Value > 0)
			{
				ContentComment comment;
				ContentPage contentpage;
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					comment = (from c in db.ContentComments
							   where c.CommentId == id.Value
							   select c).Single();

					contentpage = (from p in db.ContentPages
								   where p.PageId == comment.PageId
								   select p).Single();

					ContentComment edited = GetCommentFromCollection(id.Value, collection, false);

					comment.Approved = edited.Approved;
					comment.Author = edited.Author;
					comment.AuthorEmail = edited.AuthorEmail;

					comment.BodyHtml = edited.BodyHtml;
					comment.BodyText = edited.BodyText;

					// Important to save changes here as the next step alters the model.
					db.SubmitChanges();

					comment.ContentPage = contentpage;

					pageid = comment.PageId;

					ViewData.Model = comment;
				}
			}

			// There was no page or something went wrong
			if (pageid == 0)
				return RedirectToAction("Index");

			return RedirectToAction("Read", new { id = pageid });
		}

		/// <summary>
		/// Deletes a given comment
		/// </summary>
		/// <param name="id">Comment Id</param>
		/// <returns>Delete comment view</returns>
		public ActionResult DeleteComment(int? id)
		{
			int pageid = 0;
			if (id.HasValue)
			{
				ContentComment comment;
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					comment = (from c in db.ContentComments
							   where c.CommentId == id.Value
							   select c).Single();

					pageid = comment.PageId;
				}
				ViewData.Model = comment;
				return View();
			}
			return RedirectToAction("Read", new { id = pageid });
		}

		/// <summary>
		/// Deletes a given comment
		/// </summary>
		/// <param name="id">Comment Id</param>
		/// <param name="collection">Form input data</param>
		/// <returns>Back to read page index</returns>
		[HttpPost]
		public ActionResult DeleteComment(int id, FormCollection collection)
		{
			try
			{
				int pageid = 0;
				using (SimpleCMSDataContext db = new SimpleCMSDataContext())
				{
					ContentComment comment = (from c in db.ContentComments
											  where c.CommentId == id
											  select c).Single();

					pageid = comment.PageId;
					db.ContentComments.DeleteOnSubmit(comment);
					db.SubmitChanges();
				}
				return RedirectToAction("Read", new { id = pageid });
			}
			catch { }
			return RedirectToAction("Index");
		}

		/// <summary>
		/// Gets a ContentPage object from the given form data
		/// </summary>
		/// <param name="id">Parent Id</param>
		/// <param name="collection">Form data input</param>
		/// <param name="newpage">True if creating a new page, false if editing</param>
		/// <returns>New ContentPage</returns>
		private ContentPage GetPageFromCollection(int id, FormCollection collection,
			bool newpage)
		{
			// Setup markdown
			Markdown m = new Markdown();

			// New page
			ContentPage content = new ContentPage();

			// Trigger date
			DateTime dt = DateTime.Now;

			// Basics
			content.ParentId = id;
			content.Title = Util.DefaultString(collection["title"], "No title");
			content.Description = Util.DefaultString(collection["description"], "");

			if (newpage)
			{
				content.Author = Util.DefaultString(collection["author"], "Anonymous"); // Just for now
				content.AuthorId = 0; // Just for now
			}

			// Page content
			content.AbstractText = Util.DefaultString(collection["abstracttext"], "");
			content.AbstractHtml = m.Transform(content.AbstractText);

			content.BodyText = Util.DefaultString(collection["bodytext"], "");
			content.BodyHtml = m.Transform(content.BodyText);


			// Eenable publishing
			content.Approved = Util.DefaultBool(collection["approved"], true);

			if (newpage)
			{
				// Nested
				content.ViewCount = 0;
				content.CommentCount = 0;
				content.PageCount = 0;

				// Times
				content.CreatedDate = dt;
			}

			// Pubdate
			content.PubDate = Util.DefaultDate(collection["pubdate"], dt);

			// Every time this function is called, we're doing something to the page.
			content.LastModified = dt;

			// Feedback
			content.EnableComments = Util.DefaultBool(collection["enablecomments"], true);
			content.AnonComments = Util.DefaultBool(collection["anoncomments"], true);
			content.Moderated = Util.DefaultBool(collection["moderated"], false);

			return content;
		}

		/// <summary>
		/// Gets a ContentComment object from the given form data
		/// </summary>
		/// <param name="id">Page Id</param>
		/// <param name="collection">Form data input</param>
		/// <param name="newpage">True if creating a new comment, false if editing</param>
		/// <returns>New ContentComment</returns>
		private ContentComment GetCommentFromCollection(int id, FormCollection collection,
			bool newcomment)
		{
			// Setup markdown
			Markdown m = new Markdown();

			// New comment
			ContentComment comment = new ContentComment();

			// Trigger date
			DateTime dt = DateTime.Now;


			// Author name
			comment.Author = Util.DefaultString(collection["author"], "Anonymous");

			if (newcomment)
			{
				// Basics
				comment.PageId = id;
				comment.AuthorId = 0; // Just for now
				comment.AuthorIP = Util.GetUserIP();
				comment.CreatedDate = dt;
			}

			comment.LastModified = dt;

			// We don't have an approval yet
			comment.Approved = true;
			comment.AuthorEmail = Util.DefaultString(collection["authoremail"], "");

			// Content
			comment.BodyText = Util.DefaultString(collection["bodytext"], "");
			comment.BodyHtml = m.Transform(comment.BodyText);

			return comment;
		}
	}
}

Onward to page 2…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s