The simplest possible CMS with CMarkdown and Yii

Well saying "CMS" means a huge over-interpretation here. This article shows how to actually write the quickest and the simplest possible rich-text page content render for rendering Markdown-formatted texts stored in separate .txt files.

The entire article is actually a single Yii action plus an example on how to call it.

This solution uses CFile extension. More information about Markdown formatting, used here, can be found at this page or in Yii doc for CMarkdown class.

This solution assumes following:

  • texts are formatted using Markdown and are stored in separate files,
  • each file contains page's title in the first line and actual content in remaining lines,
  • files has fixed path (files/pages/), where they're stored, and fixed extension (.txt).

To render Markdown-formatted texts stored in separate class I'm using this simple action:

/**
 * This is the default 'index' action that is invoked when an action is not 
 * explicitly requested by users. It is also used to display texts form external
 * files with (or without) Markdown formatting.
 * 
 * This function uses CFile extension (http://www.yiiframework.com/extension/cfile).
 * 
 * More information on Markdown-style text formatting can be found under this
 * address: http://daringfireball.net/projects/markdown/syntax or in Yii doc
 * about CMarkdown class: http://www.yiiframework.com/doc/api/1.1/CMarkdown/.
 * 
 * @param string $page          Page name, here transformed to full filename.
 * @param boolean $withMarkdown Whether to show contents "as-is", without Markdownformatting.
 * 
 * @throws CHttpException       A standard exception, if given page does not exits.
 */
public function actionIndex($page = '', $withMarkdown = true)
{
    if($page !== '')
    {
        $filename = 'files/pages/'.$page.'.txt';
        $file = Yii::app()->file->set($filename);
        
        if($file->exists)
        {
            $data = explode("n", $file->getContents());
            $title = array_shift($data);
            $body = implode("n", $data);
            
            if($withMarkdown === true)
            {
                $markdown = new CMarkdown;
                $contents = $markdown->transform($body);
            }
            else $contents = $body;
            
            $this->render('page', array
            (
                'title'=>$title,
                'contents'=>$contents
            ));
        }
        else throw new CHttpException(404, 'Invalid request. Please do not repeat this request again.');
    }
    else $this->render('index');
}

Actions arguments are:

  • a valid path to .txt file (required).
  • disable Markdown formatting; enabled by default (optional).

When everything is OK, this action reads contents of $page file and renders it using CMarkdown class. Action throws standard CHttpException exception, if given page (file) does not exits.

Above action generates following variables:

  • markdown formatting result (returned by CMarkdown::transform method) is fetched to $contents variable,
  • page's title is fetched to $title variable

and thus my view file for above action can be as simple as:

<?php
    /* @var $this MainController */

    $this->pageTitle = Yii::app()->name.' - '.$title;
    $this->breadcrumbs = array($title);
?>

<?php echo($contents); ?>

Because:

  • index action is default one in my MainController,
  • I have URL-rewriting in Yii set to use "pretty" URLs,
  • I'm using .html suffix in the end of each URL,

I can render each of my info-like pages with URLs as simple (and "pretty") as:

http://www.example.com/main/about.html

Where about refers to /files/pages/about.txt file in my application's main folder.

You may be interested in reading this blog post as well. It discussed problem of writing correct (for Yii) links in external Markdown-formatted text files, as shown in current article.

Leave a Reply