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.
-
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.