What is a Content Management System? It's a system that manages content. Any definition more specific than that is bound to make someone leave nasty flames in your inbox. There are simply too many diverse systems out there covered by the blanket term "CMS".

This module was orginally inspired by what I found to be a design flaw in SSI. Essentially, SSI forces your content to "pull in" the data from each content file. While this is less redundant than purely static content, it's still not quite good enough. I relized that a simple CMS, combined with HTML::Template and mod_perl, could fix the problem by taking the opposite approach--have the overall template pull in your content.

The result is documented below. Code is done, but I still need to package it up for CPAN. It's currently coded for Apache2 (because that's what I had available to experiment with), but it doesn't use many fancy features over Apache 1.3, so porting it shouldn't be a problem.


NAME

  Apache::QuickCMS - A small content management system


SYNOPSIS

  <Directory /var/www/data>
        <FilesMatch "\.(inc)$">
                PerlSetVar UseCache            1
                PerlSetVar TemplateFile        index.tmpl
                PerlSetVar DefaultContentType  text/html
                # Don't need extra features of perl-script, and
                # modperl is faster
                SetHandler modperl
                PerlResponseHandler Apache::QuickCMS
        </FilesMatch>
  </Directory>


DESCRIPTION

Implments a small content management system. Each directory on your web server contains a template file in HTML::Template format. The template contains TMPL_VARs at the locations you wish to fill data into.

Each document contains a POD-like format that gives the data to fill into each TMPL_VAR.


USAGE

Configuration

UseCache

Default: 1

Cache the output to the disk. The cache file will be used if this is set to a true value, a cache file exists, and the modification times of the include file and the template are less than or equal to the modification time of the cache file. You can force a cache update by either running touch(1) on the include file or template or by deleting the cache file.

CacheExt

Default: .cache

When using caching, this controls what file extention to save the cache under.

TemplateFile

Default: index.tmpl

Controls what file to use as the template for each directory. If this file does not exist in the document's directory, the one for the next directory down is used. It will keep searching in each parent directory until it finds a template file or it runs out of parent directories.

DefaultContentType

Default: text/html

If no content type is set inside the document, then this type is set instead.

Documents

Template

The templates are in HTML::Template format. Because of the way it's used, TMPL_LOOP tags aren't useful.

Each directory can contain a different template, saved to the file noted by the TemplateFile parameter in your Apache configuration.

For every TMPL_VAR and TMPL_IF you have, you can place an entry for it in your include file. Here's an example:

  <html>
  <head>
        <title><TMPL_VAR title></title>
  </head>
  <body>
        <TMPL_VAR content>
  </body>
  </html>

This template would thus have an include file with directives for title and content.

Directives

The directives have a POD-like format. A directive named content_type is a special case (see below). An example for the tempale above would be:

  =title
        Hello
  =cut
  
  =content
        <p>Hello, world!</p>
  =cut

Save this document as index.inc (you may want to modify your Apache's DirectoryIndex attribute). You make a request for http://www.example.com/index.inc and (if properly configured) you will receive the above filled into the associated template entries.

The first POD-like directive is the name of the template variable, and everything after that up until =cut will be filled into that spot in the template. Anything not enclosed between a directive and a =cut will be ignored. If you specify the same directive twice in one file, the last one wins (this may change).

You may place any valid HTML::Template tags inside the directives. This is primarily for TMPL_INCLUDE tags. Other tags aren't particularly useful, since there is no way of getting data into them. I suggest limiting the use of this feature, since over-use will get you as many problems as SSI.

Content-type

If you want to override the HTTP Content-type header being sent, you can specify a directive called content_type.

  =content_type
  text/plain
  =cut

It's best to eliminate whitespace before the actual content-type, including a blank line (but you do need a newline after the =content_type text).


TESTING

The tests in the t/ directory of this package hardly constitue a good test suite. If you wish to give a good test, you need to configure it yourself and add a PerlSetVar Debug 1 in the Apache config. You then setup the situations described here while doing a tail -f on your Apache error log.

After configuration and restarting Apache, use the files in the examples/ directory of this package, and then setup the situations below.

With Caching Turned Off

Make a request for the text_parse.inc file. It should give back a valid page with a Content-Type of text/plain.

Remove the =content_type section of text_parse.inc (you may wish to keep a backup copy around). It should now give back the same page with a Content-Type of 'text/html'.

Reconfigure Apache with PerlSetVar DefaultContentType text/rtf and restart Apache. Make a request for the same page. You should get the same data with the a Content-Type of text/rtf.

Now set your configuration back, turn on caching, and restart Apache.

With Caching Turned On

You'll want to tail -f your Apache error log, and be sure to have PerlSetVar Debug 1 in your Apache configuration.

Make a request for text_parse.inc. It should send back the page, and the error log should indicate that a cache file was not available and was created.

Make another request for text_parse.inc. It should send back the same page, but the error log should say that the cache file was used.

Run touch(1) on index.tmpl and make a request for text_parse.inc. The error log should say that a new cache file is created.

Make another request for text_parse.inc. It should send back the same page, but the error log should say that the cache file was used.

Run touch(1) on text_parse.inc and make a request for text_parse.inc. The error log should say that a new cache file is created.

Make another request for text_parse.inc. It should send back the same page, but the error log should say that the cache file was used.

Remove the cache file. The error log should say that a cache file was not available and was created.

Make another request for text_parse.inc. It should send back the same page, but the error log should say that the cache file was used.

Modify the Apache configuration to use a different cache file extention and restart Apache. Make a request for text_parse.inc. It should create a cache file with the extention you specified.


BUGS

Yes.


SEE ALSO

HTML::Template. mod_perl2. touch(1). perlpod(1).


COPYRIGHT

Apache::QuickCMS Copyright (C) 2004 Timm Murray

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


AUTHOR

  Timm Murray <tmurray@wumpus-cave.net>
  CPAN ID: TMURRAY

----
send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.

Replies are listed 'Best First'.
Re: RFC: Apache::QuickCMS
by perrin (Chancellor) on May 28, 2004 at 17:08 UTC

      I wanted to use HTML::Template for this project for the specific reason that I expect it to be used by people who understand HTML but don't do programming. That's exactly the situation HTML::Template was created to handle.

      ----
      send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.

        Hmmm, that is exactly the situation Template Toolkit was created to handle too. It has functionally equivalent syntax for all of the tags you are using. The only additional part would be telling it which file to load the data from:
        [% USE mydata = datafile('/path/to/datafile') %]
        That piece could be stuffed into an Apache::Template subclass or a master template if it looks too scary.
        That sounds like you're confusing layout vs. content. I would assume you'd have 2-3 templates and 200-300 different documents. Maybe a template for press releases, another for FAQs, etc.

        I would think you'd be creating the templates once and editing them rarely, if ever. The content will be provided, probably, by someone who knows nothing about the web, including HTML. (In fact, it's very likely that a Word document would be provided ...)

        ------
        We are the carpenters and bricklayers of the Information Age.

        Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

        I shouldn't have to say this, but any code, unless otherwise stated, is untested

      Would you mind providing a short tutorial with a basic example? I'm a novice to TT and would love to provide this for the marketing group (so we don't have to manually add all the press releases).

      ------
      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I shouldn't have to say this, but any code, unless otherwise stated, is untested

        There's a tutorial about how to generate a tree of static pages in a Makefile-like way here. There's more documentation in the modules I mentioned. You can also buy the very comprehensive O'Reilly book (or read it on their Safari service).