NAME

Posy::Core - the core methods for the Posy generator

VERSION

This describes version 0.11 of Posy::Core.

SYNOPSIS

# implicitly
use Posy qw(Posy::Core Posy::Plugin::TextTemplate ...);

# or explicitly
require Posy;

@plugins = qw(Posy::Core Posy::Plugin::TextTemplate ...);
Posy->import(@plugins);
Posy->run(%args);

DESCRIPTION

This is a simple website content management system inspired by the design of blosxom. The filesystem is the database, there are flavour templates, and plugins. However, this system doesn't require one to write one's entry files in a particular format; one can choose from pure HTML, plain text, or blosxom format. And other formats can be dealt with if one writes a plugin to deal with them.

Posy::Core provides the core functionality of the system. Other functions can be added and overridden by plugin modules.

CLASS METHODS

run

Posy->run(%args);

run is the only method you should need to use from outside this module; other methods are called internally by this one.

This method orchestrates all the work; it creates a new object, and applies all the actions.

Arguments include:

actions

The actions that should be performed by the Posy engine. If none are given, then the default sequence will be used.

entry_actions

The actions which should be performed on each entry. If none are given, then the default sequence will be used.

data_dir

The directory where the data is.

state_dir

The directory where the state-related data is (what used to be "plugins/state" in blosxom).

TERMS

A few terms:

data_dir, data directory

The directory where the input data files are kept. This need not be the same directory as the posy.cgi script or any other script. This is set up with sub-directories in a hierarchical fashion and chiefly contains the files holding the web content you wish to display.

state_dir, state directory

The directory where "state" files are written. Thus this needs to be a directory writable by the script, which may need special care when using Posy with a CGI script, since the user and permissions tend to be tricky with CGI scripts.

config_dir, config directory

The directory where configuration files are kept, in a hierarchical manner which mirrors that of the data directory. This defaults to being the same directory as the data_dir.

flavour_dir, flavour directory

The directory where flavour files are kept (see "flavour"), in a hierarchical manner which mirrors that of the data directory. If not defined, this also defaults to the same directory as the data_dir.

full path, full filename

The absolute location of a given file; the absolute pathname.

path

(a) the relative location of a file (relative to the data directory or to the top of the website, depending on context) (b) the current request path (which may or may not be the relative location of a file)

path-type

The type of request path. This can be "entry", for an individual file, "category", for a sub-directory, "chrono" for a dated request, "top_entry" for an entry at the top of the website, "top", for the very root page, or "file" for a file which is not an entry. (These may change slightly in future).

chunk

A given output page is pasted together from several chunks, each of which has a template for it. The chunks are:

content_type

The MIME-type of the output page. Usually this is text/html, but some veriations may call for text/plain or something else.

The "head" part of the page; which usually includes the opening <html> tag, the <head> content, and the opening <body> tag and any initial content required.

A header part of a page; something which may or may not be repeated over the page, depending on how its contents change.

entry

The template for the actual page content; for pages which source multiple entry-files per page, this is repeated for each entry file. An entry file is just an individual input content file.

The "foot" part of the page; usually contains trailing content, and the closing </body> and </html> tags.

flavour

The Posy system, like the blosxom system, enables use of multiple template-sets by giving them a "flavour" extension, which can be parsed from the initial request path by either the extension of the request path, or by a "flav" paramter. One can then set up a different template-set for each flavour, and customize the look of the output pages while keeping the content separate.

OBJECT METHODS

Documentation for developers and those wishing to write plugins.

new

Make a new object. See "run" for the arguments.

init

Do some initialization of the object after it's created. Set up defaults for things which haven't been defined.

Plugin writers should override this method rather than "new" if they want to do some initialization for their plugin.

do_actions

$self->do_actions();

Do all the actions in the $self->{actions} list. (Called from "run").

Flow Action Methods

Methods implementing actions. All such methods expect a reference to a flow-state hash, and generally will update either that hash or the object itself, or both in the course of their running.

set_config

$self->set_config($flow_state);

Set $self->{config} from the config files. Takes into account the path, but does not use chunk information; useful for setting global parameters.

init_params

Parse the global parameters. Creates a CGI object in $self->{cgi} and checks whether we are in a CGI environment (dynamic) or not (static) and sets $self->{dynamic} and $self->{static} accordingly.

Note that "static" does not mean the same thing as with blosxom2; what actions are performed depend entirely on the $self->{actions} array; it won't be trying to generate all the files just because we aren't in CGI mode.

Sets $self->{url} if it isn't already set.

When this is not in dynamic mode, the parameters can be set by passing them through the $self->{params} hash (by setting params=>{...} when calling "new" or "run". This can be useful for writing scripts that aren't CGI scripts.

index_entries

Find the entries files, the "other" files, and the categories. This uses caching by default.

Expects $self->{path} and $self->{config} to be set.

Sets $self->{reindex} if reindexing has been done.

parse_path

Parse the PATH_INFO (or 'path' parameter) to get the parts of the path and figure out various bits of information about the path. If the path is undefined, uses DOCUMENT_URI or REDIRECT_URL.

This checks whether or not the requested file/directory exists under the data directory.

Sets $self->{path} hash as follows:

info

The original PATH_INFO or equivalent.

type

The type of the path: entry, top_entry, top, category, chrono, file.

file_key

The path without the extension; used as a key in $self->{files}.

ext

The extension of the actual entry file or "file" file.

data_file

The full path of the found file.

basename

The base name of the file without directory or extension.

dir

The directory part of the path.

depth

The depth of the file from the top directory.

flavour

The flavour of the request.

name

The path directory with underscores instead of slashes.

year

For "chrono" paths, the year part of the request.

month

For "chrono" paths, the month part of the request. Optional.

day

For "chrono" paths, the day part of the request. Optional.

Expects parameters to have been initialized (so that it can check $self->param('path') as well as PATH_INFO).

If it fails to parse the path, sets $self->{path}->{error} to true, and $self->{path}->{info} will be the only other part set. This can be used by later actions, such as "stop_if_not_found".

stop_if_not_found

If there was an error parsing the path ($self->{path}->{error} is true) then flag the actions to stop.

Also sends a 404 error if we are in dynamic mode; this assumes that if it can't parse the path, it can't find the file.

This is done as a separate action method so that it makes it easier to change this behaviour.

select_by_path

$self->select_by_path($flow_state);

Select entries by looking at the path information. Assumes that no entries have been selected before. Sets $flow_state->{entries}. Assumes it hasn't already been set.

filter_by_date

$self->filter_by_date($flow_state);

Select entries by looking at the date-time information in $self->{path}. Assumes that $flow_state->{entries} has already been populated; updates it.

sort_entries

$self->sort_entries($flow_state);

Sort the selected entries (that is, $flow_state->{entries}) Checks $self->{config}->{sort_type} to determine the sort order. The possible types are: time, time_reversed, name, name_reversed, path, path_reversed (default: time_reversed)

content_type

$self->content_type($flow_state);

Set the content_type content in $flow_state->{content_type}

head_template

$self->head_template($flow_state);

Set the head template in $flow_state->{head_template} This also sets the $self->{config} for head.

head_render

$self->head_render($flow_state);

Interpolate the head template into the head content; Set the head content in $flow_state->{head}

foot_template

$self->foot_template($flow_state);

Set the foot template in $flow_state->{foot_template} This also sets the $self->{config} for foot.

foot_render

$self->foot_render($flow_state);

Interpolate the foot template into the foot content; Set the foot content in $flow_state->{foot}

do_entry_actions

$self->do_entry_actions($flow_state);

Process the $self->{entry_action} list.

render_page

$self->render_page($flow_state);

Put the page together by pasting together its parts in the $flow_state hash and print it (either to a file, or to STDOUT). If printing to a file, don't print content_type

Entry Action Methods

Methods implementing per-entry actions.

count_or_stop

$self->count_or_stop($flow_state, $current_entry, $entry_state)

Increment the $flow_state->{entry_count} and stop the processing of this entry if it goes beyond the required number in $self->{config}->{num_entries}.

header

$self->header($flow_state, $current_entry, $entry_state)

Sets the entry date vars for this entry, in $curent_entry. See "nice_date_time" for details.

Also sets the same variables in $flow_state, so that the values for the last-processed entry will be preserved (useful for doing entry-specific things in foot templates).

Set the header content in $flow_state->{header} and add the header to @{$flow_state->{page_body}} if it is different to the previous header.

read_entry

$self->read_entry($flow_state, $current_entry, $entry_state)

Reads in the current entry file. Sets $current_entry->{raw} with the contents.

parse_entry

$self->parse_entry($flow_state, $current_entry, $entry_state)

Parses $current_entry->{raw} into $current_entry->{title} and $current_entry->{body}

entry_template

$self->entry_template($flow_state, $current_entry, $entry_state)

Set the entry template in $entry_state->{entry_template} This also sets the $self->{config} for entry.

render_entry

$self->render_entry($flow_state, $current_entry, $entry_state)

Interpolate the current entry, setting $entry_state->{body}.

append_entry

$self->append_entry($flow_state, $current_entry, $entry_state)

Add $entry_state->{body} to @{$flow_state->{page_body}} (This is done as a separate step so that plugins can alter the entry before it's added to the page).

Helper Methods

Methods which can be called from within other methods.

param

my $value = $self->param($name);

Return or set global parameters.

This passes the arguments on to $self->{cgi}->param(); See CGI::Minimal for more information.

set_vars

my %vars = $self->set_vars($flow_state);

my %vars = $self->set_vars($flow_state, $current_entry, $entry_state);

$content = $self->interpolate($chunk, $template, \%vars);

Sets variable hashes to be used in interpolation of templates.

This can be called from a flow action or from an entry action, and will use the given state hashes accordingly.

This sets the variable hash as follows:

$self->{I<name>} where it is a simple value (eg 'url') -> $I<name>
$self->{path}->{I<name>} -> $path_I<name>
$self->param('I<name>') -> $param_<name>
$self->{config}->{I<name>} -> $config_<name>
$flow_state->{I<name>} -> $flow_<name>
$current_entry->{I<name>} -> $entry_<name>
$entry_state->{I<name>} -> $es_<name>

get_template

my $template = $self->get_template($chunk);

Get the template file for this state, taking into account $self->{path}->{dir}, $self->{path}->{type}, $self->{path}->{flavour}, and of course $chunk

Returns (a copy of) the found template. This is so that the following actions can alter the template as they see fit.

Possible chunks are "content_type", "head", "header", "entry", "foot". The "header" and "entry" chunks are used during entry processing.

The template files are called $chunk.$path_type.$flavour or $chunk.$flavour

get_config

my %config = $self->get_config($chunk);

Get the config settings for this state, taking into account $self->{path}->{dir}, $self->{path}->{type} and $chunk

Possible chunks are nothing, "content_type", "head", "header", "entry", "foot".

The config files are called

$path_type.$chunk.config
$path_type.config
$chunk.config
or
config

Returns a hash of cumulative config settings.

read_config_file

$self->read_config_file($filename);

Read the given config file, and return a hash of config settings from it. The $filename is the full name of the file to read.

The config file is made up of name:value pairs of data.

interpolate

$content = $self->interpolate($chunk, $template, \%vars);

Interpolate the contents of the vars hash with the template and return the result.

(This is passed the chunk name just in case a future plugin which overrides this method wishes to do something different depending on what chunk type it is.)

nice_date_time

my %nice_vals = $self->nice_date_time($mtime);

Given a unixtime (in seconds since whenever it was) will return a hash containing the portions of the date-time:

sec

The second.

min

The minute.

hour

The hour (24-hour time).

year

The 4-digit year.

mnum

The number of the month (1-12).

da

The day of the month.

wday

The day of the week (number).

dw

The day of the week (name).

month

The month name.

debug

$self->debug($level, $message);

Print a debug message (for debugging). Checks $self->{'debug_level'} to see if the message should be printed or not.

Private Methods

Methods which may or may not be here in future.

_whowasi

For debugging: say who called this

_find_file_and_ext

($fullname, $ext) = $self->_find_file_and_ext($path_and_filebase);

Returns the full path file and the extentsion of the given path-plus-basename-of-file; if no matching entry file exists under the data directory, the returned values are empty strings.

_wanted

$self->_wanted();

This is a method called from a wrapper 'wanted' function inside the call to File::Find::find inside the index_entries method. This does all the work in indexing the entries.

_init_caching

Initialize the caching stuff used by index_entries

_read_caches

Reads the cached information used by index_entries

_save_caches

Saved the information gathered by index_entries to caches.

extract_date

Given a unixtime (in seconds since whenever it was) will return an array containing the 4-digit year, the month (1-12) and the day of the month.

_url

Figure out the full url.

_protocol

Figure out the protocol. (taken from CGI::Simple)

_server_port

And the server port.

_server_protocol

And the server protocol.

REQUIRES

File::Spec
File::stat

File::Find
Storable
CGI::Minimal

Test::More

SEE ALSO

perl(1). Posy

BUGS

Please report any bugs or feature requests to the author.

AUTHOR

Kathryn Andersen (RUBYKAT)
perlkat AT katspace dot com
http://www.katspace.com

COPYRIGHT AND LICENCE

Copyright (c) 2004-2005 by Kathryn Andersen

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.