Award Winning Design

Tactical Web Development

Effective SEO Marketing


Customizing Graffiti CMS

Wednesday, October 01, 2008

I have been having some fun figuring out how to extend Graffiti CMS and Chalk for our site.  When I am finished, I will post the source code of our Actualize extensions for others to use and improve upon.

 

One of the challenges I was faced with in building the site was dealing with content dispursed in different sections of our layout.  This is not a traditional site layout or blog type CMS template.  So what I did was use customized .view files and some logic to determine which 'page' needed to be rendered, and to grab specific posts for the various template regions.

 

For example, this page, if you notice the URL, is 'http://www.actualizestudio.com/services/develop_blog/customizing-graffiti-cms/'.  I created a category for each of the top menu items on our page except for 'Home'.  So there are services, team, work, and contact categories.  Services has 3 subcategories: develop, design, and seo.

 

So in my layout.view file, I have a simple check to load a specific category view for the left column:

 

#if($category.name=="Services"||$category.Parent.name=="Services")
          $macros.LoadThemeView("services_left_column.view")

 

In the 'services_left_column.view' file, I have further checks to see what subcategory the user selected, and then loads the post for that specific subcategory left column text:

 

#set($post = $data.GetPost("services_design_left_column"))
              $post.Body

 

In the right column, I use a post for the top image and right column large type text:

 

#set($post = $data.GetPost("services_design_right_column"))
              $post.Body

 

And then underneath, I created another subcategory called, in this case, design_blog.  I found the Graffiti Chalk Extensions online, and using them I created a loop to show all of the posts assigned to this design_blog:

 

  #set($gdPosts = $ChalkExtensions.GetAllPostsForCategory("design_blog"))
  #set($gdPosts2 = $ChalkExtensions.SortPostsAscending($gdPosts, "Published"))
  #foreach($post in $gdPosts2)
   <img src="$macros.ThemeFile("images/line.png")">
   <h1 class="title">$post.Title</h1>
   <div class="meta">$post.Published.ToString("dddd, MMMM dd, yyyy")</div>
   <div class="entry">
    <p>
     $post.Body
    </p>
   </div>
 

 

This would work great for all of the content in the various sections of the site.  However, when we decided to add a blog to each of the services subcategory pages, I stumbled upon an issue.   Graffiti provides a $comments collection object that can be used to loop through and display any comments for a particular post.  Problem is, this $comments collection appears to be defaulted to populate based on the default post that should be assigned to that subcategory.

 

So what I needed was a way to get a collection of comments for a particular post through code.  Hmmmmm.  I emailed Graffiti support, but since they were in no rush and I was, I was forced to bust open Visual Studio and get crackin.  I also decided to throw in a little function to allow me to read in values passed in the querystring, so I could add some more functionality later.  I also have some other stuff hiding in there that I am not going to show you here, so you can ignore the System.Data and System.Data.SqlClient references.

 

using DataBuddy;
using Graffiti.Core;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web;

namespace Actualize
{
    [Chalk("Actualize")]
    public class Extensions
    {
        public CommentCollection CommentsForPost(int PostId)
        {
            CommentCollection comms = new CommentCollection();
            Query q = Comment.CreateQuery();
            q.AndWhere(Comment.Columns.PostId, PostId);
            q.AndWhere(Comment.Columns.IsPublished, true);
            q.AndWhere(Comment.Columns.IsDeleted, false);
            q.OrderByAsc(Comment.Columns.Published);

            comms.LoadAndCloseReader(q.ExecuteReader());
            return comms;
        }
       
        public string GetValueFromQueryString(string Key)
        {
            string result = "";

            HttpRequest req = (HttpRequest)HttpContext.Current.Request;
            result = req[Key];

            return result;
        }

 

 

After compiling the project and moving the Actualize.dll file over to the site's bin directory, I needed to tweak the code in my .view file:

 

    #set($thisPostsComments = $Actualize.CommentsForPost($post.Id))
     #foreach($comment in $thisPostsComments)
 

 

and then display the comments.... Voila!  Success.