The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Miril::Hacking - Miril Developer's Guide

ABOUT

This documents provides an overview of how Miril works under the hood and makes it easier for developers to start hacking.

ARCHITECTURE

Framework

Miril uses CGI::Application as its base framework.

Configuration

Miril currently allows configuration only in XML format, but other formats will probably be added in the future. The required parser will probably be guessed from the extension of the configuration file.

Currently the configuration file is processed by Miril::Config. It adds some defaults and simplifies some data structures. It returns a configuration object, which is a Data::AsObject hashref. XML::TreePP is used for parsing XML, since it is lightweight and pure perl.

The configuration format does not follow a specific structure, and new elements may be freely added when needed by third-party Miril plugins.

Authentication and user management

CGI::Application::Plugin::Authentication is used to authenticate users. The generic driver is used with a custom verification callback provided by Miril::UserManager::XMLTPP.

A special file (or a databse) is used to manage users and their passwords. A module in the Miril::UserManager namespace takes care of reading data from the users file and updating it when necessary. Currently the only Miril::UserManager::XMLTPP exists, providing an interface to a users file in XML format.

A user management module for Miril must provide the following interface:

new

A constructor

verification_callback

Returns a reference to a subroutine used to authenticate the user. The subroutine should accept two arguments - a username and a password, and should return the username if the authentication was successful, and undef otherwise.

get_user

Accepts a username as its argument and returns an object containing all user data.

set_user

Accepts a user object as its argument and updates the data about this user in the configuration file (or creates a new entry if no such user exist yet).

delete_user

Accepts a username as its argument and attempts to delete this user from the configuration file.

encrypt

Receives a plain-text password as its argument and returns its encrypted representation.

The user object has the following structure:

username

The username used for logging into Miril.

name

The real name of the user or any other desicriptive text.

password

The user's password.

email

The user's email.

The user interface

Miril uses HTML::Template to generate its user interface. The actual templates are embedded in Miril::Theme::Flashyweb and Miril::Theme::Flashyweb::Stylesheet. The load_tmpl method in Miril::Util loads the requested template. The theming system is designed to be extensible, and support for using different themes and templating engines is planned.

Model (storage)

Miril can store its data in plain text files or in a database (database support is not implemented yet). A class in the Miril::Model namespace takes care of all functions related to reading and writing data. Its interface is as follows:

new

Constructor.

get_post

Receives as its argument the ID of a post, and returns a post object.

get_posts

Optionally receives as an argument search criteria provided as a hash (e.g. "title", "author", "status", etc.) and returns all matching posts. If no arguments are supplied, returns a list of all posts.

save

Receives as its argument a post object, and updates it or creates it in the database.

delete

Receives as its argument the ID of a post, and deletes it from the database.

The contents of the post object is described in Miril::Manual.

Currently only Miril::Model::File::XMLTPP is availabe. It writes the body of posts to individual files named as their respective post ID. Metadata for all posts is written in a separate file, data.xml. Plans are to refactor this class so that metadata for each post is written in the same file as the post itself, and data.xml acts only as a cache for metadata.

View (templating systems)

A view for Miril is a templating engine used to publish data from its database to html. It is the templating language used by Miril users to create the templates for their website, and it may be different from the templating language used to display Miril's user interface theme. Currently Miril supports HTML::Template and Text::Template views. A view must inherit from Miril::View::Abstract and provide a single method: load. This method receives two named arguments: name and params. name is the name of the requested template, as specified for each post and list type in the Miril configuration file. params is a hashref with variables to be passed on to the templates (normally these will be $post for ordinary posts and $posts for lists).

Filters

Filters convert text in various formats (e.g. Markdown, Textile, etc.) to HTML. Filters reside in the Miril::Filter namespace.

The Miril object

Miril passes a copy of the miril object to the constructor of each plugin class (that means models, views, filters, etc.). It is used primarily to get to the config object and to the error processing function (see below).

Utility functions

The Miril::Util package provides a bunch of uitility functions for Miril.

CODING GUIDELINES

Object-oriented programming

Miril currently does not use any specific object-oriented programming framework. Properties are set via direct access to the members of the underlying hashref. Accessor methods are defined at the end of each class.

Exception handling

Miril currently uses Try::Tiny for exception handling. Plans are to start using autodie in the near future as well.

Miril uses a special error handling mechanism provided by the process_error method of the miril object. It is meant to be used inside of a catch clause instead of warn or die. It receives three arguments: a user-friendly error message, the actual error message as provided by $! (or $_ when using Try::Tiny), and an optional third boolean argument specifying whether the error is to be treated as fatal or not. Using this functionality, whenever errors occur Miril will present them in a nicely formatted list within the Miril user interface, so as not to scare the end user.

All of Miril's error related functions are defined in Miril::Error.

Dependencies

The goal of Miril is to be as lightweight on dependencies as possible, without reinventing the wheel. At some point in the future, I would like to be able to ship Miril, along with all of its dependencies, either as a single file, or as modules in a local::lib that can simply be uzipped and used. So all core Miril depndencies should be pure perl and consist of as few files as possible. Many of the modules Miril uses have been choses precisely because they match these criteria (CGI::Application, HTML::Template, XML::TreePP, etc.).

AUTHOR

Peter Shangov, <pshangov at yahoo.com>

COPYRIGHT & LICENSE

Copyright 2009 Peter Shangov.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.