Guide
=============================================================================

	- The CHeMS Guide


-----------------------------------------------------------------------------
Please, help me to correct this guide. I tried to write in english as better
as possible but i'm pretty sure there are lots of errors which you can notice
to me by sending a feedback. Thanks!
-----------------------------------------------------------------------------


0. Index
   1. Introduction
      1.1. What's CHeMS?
      1.2. Why CHeMS?
      1.3. Where to start?
   2. Files overview
      2.1. The root directory (chems-x.y)
      2.2. The "docs/" directory
      2.3. The "src/" directory
      2.4. The "themes/" directory
      2.5. The "usr/" directory
   3. Configuration and basic usage
      3.1. Paths and files
      3.2. Objects (posts_mgr and pages_mgr modules)
      3.3. Multiple instances
   4. Themes
   5. Modules
   6. Writing modules
      6.1. Concepts
      6.2. Files and paths
      6.3. Functions: _main and _page
      6.4. Hello world module
      6.5. Globals variables
      6.6. Format operators
      6.7. TFB DB API
      6.8. Handling multiple instances
   7. Internals
      7.1 Design
      7.2 Divs hierachy
   8. Conclusions


* Introduction

This document provide a brief introduction to CHeMS. After read this you will
know the basics and you'll be able to do the standard operations in order to
manage your web applications (site, weblog, etc) and writing modules.


. What's CHeMS?

There are differents points of view and everyone can find about a new
definition everyday. I like to say that CHeMS is not a Content Management
System (CMS) due to its interface which force the users to deal directly
with the source code, in any case. It simply assists people through the
implementation of their web application leaving the "boring" side of this
process out of the user work. You only have to think about content (text,
images, etc.) and how this should be shown to the visitors (possibly by
playing with the CSS). The basic structure is delegated to the CHeMS core so
as more features are delegated to the external modules (comments system, RSS
feeds, etc.). That's why CHeMS is not a CMS but rather it's a Content Helper
Management System (CHMS, from there its name).


. Why CHeMS?

Someone could say: why the hell you wrote another CMS-like software? Does
other web management softwares are not so good? There are several reason
behind the CHeMS project, mainly technicals but also practicals and
phylosophics. There is a large amount of good web applications which help the
users through the creation of a site or blog but nobody of this is like
CHeMS. That's the point: CHeMS is full code-driven, this mean that you will
never get a user interface to do something. This make it more secure, stable
and customizable. Your application will be as good as your coding skills.
Another important thing to consider is that CHeMS is full compliant with the
standards XHTML-1.1 (and previous) and CSS2. This make it more interoperable
among differents browsers on differents platforms which implements this
standards (actually all the "main" browsers with the exception of Internet
Explorer) and much clear to read.  Finally, a very important thing: CHeMS is
free.  Indeed this is not much innovative but it's considered one of the most
important characteristics (there was not such applications released under 
the new GPLv3 license when i started on CHeMS, by the way). CHeMS is small,
simple and very minimalistic but it have *all* the things such software need.


. Where to start?

CHeMS is very easy to setting up and use but in order to be able to do
everything with it you should know at least the following things:

   1. where and what things are (files layout)
   2. how to add new stuff (modules), and
   3. how to customize everything.

It's quite easy to explain all these things but may be a bit more complex
writing about the internals. For this reason a specific file which discuss
about the internals of CHeMS and how to extend and hack it will be provided
soon. Anyway there is enough in this guide to make you understand how CHeMS
work in general.


* Files overview

This is a brief introduction to the CHeMS files hierachy. Nothing about
programming or hacking the software is discussed here. Please, refer to the
PHP and XHTML documentation for informations on how to change the CHeMS code.

The following is a list of all files and their descriptions.


. The root directory (chems-x.y)

This is the root directory which contains all the configuration files,
sources, modules, themes, etc. It's prefixed from "chems-" and followed by
the release name as "0.1", "5.3" (a day, maybe) or "0x03" in which case the
complete name is "chems-0x03". In this directory there are a couple of files,
the directories will be explained later.

Changes		contains a full list of all changes between the current
		release of CHeMS and the previous one. It's included in all
		versions of the software.

index.php	this is the file called before to generate any page. No other
		files are called directly and everything starts from here. It
		also declare the phisical and logical (WWW) root directories
		constants used in almost all core files.


. The "docs/" directory

As expected this directory contains all the text files, documentations
(including this file), copying informations, FAQs, etc. This is the first
directory you should look at if you are trying to play with the CHeMS source
or want to hack it. You would also read it in order to configure it as better
as possible. Therefore, the comments provided into the configuration files
and source code should be enough to let you start using CHeMS without
problems.

COPYING		license informations (essentially a copy of the General
		Public License version 3)
		
FAQs		some (hopefully useful) frequently asked question

GUIDE		a full guide to CHeMS (this file) which contains an overview
		of the software with a full description of the files hierachy
		and others useful informations

MODULES		a complete list of the modules currently released with the
		CHeMS software distribution and their relative descriptions

README		a quick introduction to CHeMS with a list of the "hot"
		features. Also contains few informations about setting up
		CHeMS.


. The "src/" directory

Here are located all the CHeMS core sources.

cdb.php		the text-file-based database API. This is the main database
		interface provided by CHeMS. Indeed there is nothing into the
		core which use this application interface but the "comments"
		module could not exists without it. For more informations
		about this interface look at the "src/cdb.php" file.

functions.php	all the routines called by the core. All the things CHeMS is
		able to do are based to the functions contained inside this
		file. It's used exlusively from the CHeMS core and should
		never be include in modules or implementations which are not
		part of the CHeMS core.

main.php	the CHeMS core. This is the file included to "index.php".
		This mean that there is nothing that CHeMS do without call
		this file indirectly throught a direct call to "index.php"
		(which includes it). The only exception is when another file
		is specified by passing the pair file/md5 with the HTTP GET
		method, in which case the given file is load instead. Into
		the main.php file is located the layout code and from there
		are called all the other routines (in "src/functions.php").
		Here is written the pages layout too.


. The "themes/" directory

This directory contains all the themes. Its content may change from
differents releases of CHeMS but, since the version 0x03, at least 3
themes are always present:

core		the core meta-theme. This is the smallest possible theme
		which include the main style directives required to start to
		write each theme. If you want to write a theme you must start
		from this one (or from another which was started from it, as
		the "monochrome" theme). It's not mandatory to have a theme
		based on "core" but doing so may be better to have a good
		start point in order to be compliant with W3C CSS2 standard.
		Also with the "core" theme make the life easier since you
		have a basic well done layout to play with.

monochrome	the default CHeMS theme (based on the core). It's the first
		theme written for the new layout introduced with the version
		0x03 of CHeMS.

colorlite	it's the only theme with colors. Its goal is to provide an
		easy-to-change theme based on a "base color" which can be
		changed with only an editor command. See the README file
		inside its directory.


. The "usr/" directory

Here are saved all the user files, from the configuration to the images to
pages and posts.
 
config.php	this is the main configuration file. Here you can customize
		the core, choose your theme, changes the CHeMS behaviour,
		edit the text for messages, menus, and so on. It's fully
		commented so you don't really need documentation at all.

images		this is not needed but it's used only to store the CHeMS
		logo. It's an indication for users which are strongly
		incouraged to put their personal files and images there
		(without populate the CHeMS tree with files here and there).

meta		tags and standard logos shown by the "meta" instance of the
		"freehands" module.

modconf.php	the modules configuration file. Here you can configured all
		aspects of the loaded modules. If you write a new module or
		add a module which has not been released with CHeMS, then it
		is here that you have to add all the configuration parameters
		(or just include the configuration file with one of the
		include*() or require*() PHP functions).

pages.inc	the user pages. All pages are stored here; see the comments
		inside this file to learn more about writing pages. Note that
		this file is not handled by the CHeMS core.

posts.inc	the user posts. All posts are stored here; see the comments
		inside this file to learn more about writing posts. Note that
		this file is not handled by the CHeMS core.


* Configuration and basic usage

The whole configuration process is based on two files located into the "usr/"
directory: config.php and modconf.php. These files contains all the possible
options for the features implemented in both CHeMS core and modules. Other
modules not released with CHeMS may require their own files or at least that
the relatives options are added into the modconf.php. Since these files are
well documented through the comments included at the top of each option,
they will not be discussed here. Useful informations about customization and
management will be shown in the following sections.


. Paths and files

The ``Files overview'' chapter explained the original CHeMS files layout.
However, it can be modified by changing the appropriate values into the
index.php file, which contains the directives specifications for the main
paths and files. This allow to use the name of the directives into the code
rather than hardcode paths which could change in further releases of CHeMS.
Also, you may need to change these paths in order to feet your needs for any
purpose you like (which is required in very few cases). There is no much to
say about, you just take in mind that you *can*, if you want.  

Currently, the following directives are defined:

NOTE: these descripitions are referring to the official CHeMS default
      configuration and may be modified partially or totally from users.
      Also you should take in mind that CHeMS is free software so you (or
      whatever else) can redistribuite modified versions of it. If you
      obtained CHeMS from a non official repository it's probably that the
      paths described here will not corespond to your configuration.

WEBROOT		logical web root directory. This is the path of the index.php
		file in a client-side form. It's used in URLs generation.

WWWROOT 	physical web root directory. This is the real path for the
		CHeMS files. It's used to deal with files from sources
		(locally).

PATH_USER	user files directory. This is the local path for the user
		files and configuration, including all the objects.
		Defined as WEBROOT."usr/".

PATH_MODULES	This directory contains all the modules. It's read from the
		CHeMS core while loading page in order to get the enabled
		modules. All modules *must* be placed here in order to works.
		Defined as WEBROOT."modules/".

PATH_THEMES	As PATH_MODULES but for the themes.
		Defined as WEBROOT."themes/".

PATH_SOURCES	This is the main CHeMS directory. All core sources (not the
		modules) are located here. If you have to deal with the CHeMS
		core this is the place for you. No other directory contains
		any of the source files for CHeMS and probably it's default
		path will never change in future.
		Defined as WEBROOT."src/".

FILE_CONFIG	The CHeMS main configuration file. Here are stored all the
		availables options for the CHeMS core and the directives used
		to load the modules (just load not configuring).
		Defined as PATH_USER."config.php".

FILE_MODCONF	As FILE_CONFIG but for the modules. Defined as
                PATH_USER."modconf.php".


. Objects (posts_mgr and pages_mgr modules)

Before to learn how to deal with objects, you should know at least what they
are and where are placed.

Techinically, an object is, on CHeMS, a collection of arguments passed to a
call to the insert() function. It's called from the CHeMS core any time a page
is loaded and is used to store all the informations about pages and posts. Since
this guide is not for programmers nor for "normal" users, the following text will
"stay in the middle" in order to show ``how it works'' to the programmers leaving
non technical users understand how to configure CHeMS without strictly dealing
with the source code.

The insert() function take one of the object variable ($PAGE or $POST) and
populate it with the given array values, key by key, value by value. As the
results an array with a list of pairs (key/value) is provided to the CHeMS
core in order to generate the pages. Each module can access this special
variable, this allow to insert module-specified values in each object (post
or page); it's very flexible. It is possible to add any pair to the array and
the insert() function will include it into the object variable. There are no
mandatory keys which you have to add, however you should always declare the
id key in order to CHeMS be able to show the object. The following the
general form used when call the insert() function:

   insert($PAGE, array(
      id => ++$pages,
      title => "Page title (id: $pages)",
      [ date => "", ]
      [ toggle => <modules list>, ]
      [ more_keys => values, ]
      body => "The post body",
   "));

The lines included between '[' and ']' are optional (all are optional but you
need at least id, title and body in order to have a "functional" object while
the other keys are just advanced configuration and customization options. For
example, the "toggle" key allow to toggle the visualization for the specified
modules when loading the current object. This is an example which show how to
toggle the ``showfiles'' and ``categories'' modules when the current page you
are viewing is the post with ID 9:

   insert($POST, array(
      id => 9,
      title => "Post ID: 0", date => "July 11 1981",
      toggle => "showfiles, categories",
      body => "The body of the post with ID 9",
   "));

You can also modify a previous declared object by changing only the
interesting keys. For example, if you want to toggle the ``showfiles'' module
again you can use the following code:

   insert($POST, array(id => 9, toggle => "showfiles"));

NOTE: all the previous calls will be replaced by the last one and the
      contrary will never happen. Be careful when choosing the order.

See the modules specified documentation (if any) to learn more about the
pairs which are provided in order to configure and customize your objects.

For completely newbies, the $posts and $pages variables are objects which
contains a number. This number may be incremented by putting the code
``++$posts'' or ``++$pages'' somewhere in the code. Usually these variables
are used to "dynamically" generate the ID of the current post or page by
putting it as value for the id key. Though these variables may be helpful,
they are not mandatory and you can totally avoid them.


. Multiple instances

Since version 0x03 of CHeMS the support for configurables multiple instances
for modules has been added. It allow a module to handle more instances of
itself in a different way, each one with its own configuration. It's
possible thanks to the ``identifiers'' which identify each instance of the
modules and generate the relatives options name for each loaded instance. An
identifier is an alphanumeric string which *must* be associated to the
"instance" key of the array() construct for each module instance declaration
(see the "usr/config.php file). This way you can load a specified module two
(or more) times with differents title, body, and so on. For example, the
``meta tags'' block of CHeMS is an instance of the "freehands" module which
use the identifier "meta" to get meta tags options value from a list of
directives names generates dinamically.

Each instance of the module use a different set of configuration directives
which names are usually generated by appending the character '_' followed by
the identifier converted in all upper case characters. See the ``Handling
multiple instances'' section of the ``Writing modules'' chapter for more
informations.

Each directives (in "usr/modconf.php") must have the same name as the
original module name directive more the postfix for the instance. For example
the "meta" instance of "freehands" which has been loaded with:

   // Meta tags
   modload("freehands", "right", "all", array(
      "instance" => "meta"
   ));

use the same name for the "freehands" directives with the "_META" suffix
added (MOD_FREEHANDS_TITLE_META, MOD_FREEHANDS_BODY_META, etc.).

If you load an istance of the "blogroll" module called "gift" as follow:

   // Gift culture (blogroll)
   modload("blogroll", "right", "all", array(
      "instance" => "gift"
   ));

to configure it you have to add to each "blogroll" configuration directive
the "_GIFT" postfix, as follow:

   define("MOD_BLOGROLL_TITLE_GIFT", "Gift culture roll");

If you want to "clone" a directive you can just use:

   define("MOD_BLOGROLL_TITLE_GIFT", MOD_BLOGROLL_TITLE);

If no identifier is specified (or it's zero) than nothing is appended to the
option name and the default is used instead.

NOTE: The multiple instances handling code is not a CHeMS feature but it's
      implemented into each module code. Actually only few modules supports
      configurable multiple instances; this is not a feature automatically
      included in all modules. Though, the CHeMS core provides an instance
      ID, unique for all modules, which enables modules to handle multiple
      instances.

For informations on how to implement such feature in your modules refer to
the ``Writing modules'' chapter below.


* Themes

Since the first release CHeMS includes a support which allow to easily handle
different themes. It just uses the values of the current theme to load the
given configuration which include lang, favicon, CSS, etc. A theme is
selected by specify its name into the CHEMS_THEME option ("usr/modconf.php")
which have to corespond to its directory name placed into the "themes/"
directory (PATH_THEMES). This directory have to contain at least a theme file
(with the ".theme" extension) which name have to be the same as that
specified into the CHEMS_THEME option (and for the theme directory name). For
a more detailed description of the theme file directive refer to the "core"
theme which should always be used as starting point for all new themes.


* Modules

Starting from the release 0x03 CHeMS becomed fully modular. This mean that
all the code which is not strictly used to load or handle the modules has
been removed from the core. Indeed, it's now only piece of code which just
load the specified (or default) module page and all the blocks loaded into
the current "scope". This made CHeMS faster, lighted and geekest.

The modules are just (not so small) piece of code which are called by CHeMS
as if they are files needed for the in-core routines or so. To be precise,
there is no differents between the CHeMS functions file and the modules one,
both are included into the main application code. The only differences is
that the modules can not deal with the page layout which is hardcoded (though
it's dynamically generated) into the "src/main.php" file.

A module may be loaded my calling the modload() function from the config.php
file which is stored into the user directory (PATH_USER - default is "usr/"),
as follow:

   modload("module_name", "sides", "modules list");

The above example load the module "module_name" in all pages which are part
of the modules listed into the "modules list" and it's placed into all the
sides specified into the "sides" list. The values in a list may be separated
as specified by the FIELD_SEPARATOR option (see "usr/config.php") and the
special value "all" is provided which is intrepreted as ``all the elements''.
Look at the modules into config.php file that are loaded by default for a
"real" example. For a list of all currently available modules just look at
the modules directory (PATH_MODULES - default is "modules/").


* Writing modules

What is a module? The short answer is ``a piece of software which, after
"plugged in" into the main application, allow to do a specific operation''.
On CHeMS it's the case of the navigation bar, the blogroll menu, and so on.
Modules allow to write better organized applications and leave the core light
and fast. You can load a module for any use and it's not considered at all
from the application since it has been loaded. The following sections explain
the main characteristics of the CHeMS modules and teach you how to write your
own modules.

NOTE: this is not a PHP or an XHMTL tutorial. You should know at least the
      basics of both these languages in order to write a useful module. If
      not, try to read the PHP and XHTML documentation first. 

Currently no API is provided (and there is no reason to assume that one will
be provided in future). The modules are totally integrated with the core,
once loaded. 


. Concepts

On CHeMS the modules are loaded by calling the module's main function which
generates and returns the code (blocks) that will be shown into the
"selected" modules page which are generated by calling the module's page
function. These functions are placed into the main file for the module which
is located into the "modules/modname/modname.php" (assuming PATH_MODULES is
set to "modules") where "modname" corespond to the name of the module. E.g.,
the main file for the blogroll module is (with the same PATH_MODULES value)
"modules/blogroll/blogroll.php". The module is a full PHP file (indeed it's
included with a call to the require_once() function and the main function is
run directly into the core) and can do everything this language allow.

Please, give a look at the current modules in order to understand how things
works.


. Files and paths

As discusses into the configuration and basic usage chapter, the CHeMS core
provides a list of directives which allow to access the layout in a compact
way. So, when you need to include some file, in almost all cases you will
have a code like this (see the discussion about paths and files above):

   require_once(PATH_USER."somefile.inc"); // Some file..

In some cases, expecially when you need to link a file in a more direct way
without delegate CHeMS to do it for you, you'll have not any directive where
to referring. In these circumstances you have to defines your own constant
trying to guess all needed paths, as in the following example:

   // The relative path for the (most likely) WWW root directory
   define("WWWROOT",                       "../../");

   // Other paths and files
   define("PATH_USER", WWWROOT.            "usr/");
   define("PATH_SOURCES", WWWROOT.         "src/");
   define("FILE_MODCONF", PATH_USER.       "modconf.php");

This code is taken from the old version of "mkfeeds.php" file of the
"rssfeeds" module. Since there was no way to get informations from CHeMS
(technically the files was not part of CHeMS but they was external and
independant) you had to set the whole files layout or at least the paths you
need in your code. Since the version 0x03 of CHeMS a new file handler has
been provided in order to "merge" the files layout with the "independant"
file. This is done by passing the file pathname with the URL (GET method)
in order to allow the index.php file to call this on rather than the CHeMS
main core file main.php. For security reasons the md5 for the given file
have to be passed too. In all cases at least two parameters have to be
passed: "chems_file" and "chems_file_md5" which have to be associated to the
filename and md5 of the file you want to get. An example link is the
following:

   // Get filename and md5
   $f = PATH_MODULES."testmod/testfile.php";
   $md5 = md5_file($f);

   // Generate the link
   $link = "<a href='?chems_file=$f&amp;chems_file_md5=$md5'>$f</a>";

Of course you can pass any additional parameters which will be handled inside
your own module routines. Since it's the simplest way to handle URIs
arguments (and do not force the users to use an HTML form) only the GET
method is used. Feel free to change CHeMS allowing a POST method interaction
or whatever you like.


. Functions: _main and _page

As introduced above, to load a module CHeMS look for a specified function
name inside a specified file in order to get the contents. The name of the
file is generated from the module's name, as follow:

   // Get the module file name
   $f = PATH_MODULES."$mod/$mod.php";

This is then included into the code and the relative function (depending on
the current module page) is called. Actually only two functions are
recognized: one for the so called "blocks" which are shown in all selected
objects and another for the custom modules generated pages which are
integrated into the CHeMS layout. The functions are generated in way similar
to the file name above appending the suffix "_main" for blocks and "_page"
for pages to the module name, as follow:

   // $f is now the module's main function
   $f = "$mod$prefix";

Where $mod is the module name passed to the function (for istance actually it
is getModFunc() - see "src/functions.php") and $prefix is one of the previous
prefix above: _main or _page. The second is used only when a module page have
to be loaded in which case the module's name have to be passed as argument
to the HTTP GET method variable "name" (or, if none, it's taken from the
value of the BASEMOD option). In all other cases "_main" is used instead.
Finally the returns value of the generated function call (the XHMTL page) is
appended to the output page. A look at the currently availables modules may
help (a lot).

When success a module have to return the generated text (the block or the
page) which will be appended to the output page. If you don't want to show
nothing at all then doesn't return nothing or 0 or an empty string. In the
case you want to explicitally show an error then a specific value must be
returned: CHEMS_MODULE_FAILURE. This inform CHeMS that the value of the
MODULES_MSG_ERROR option have to be used as current module and show.


. The _CEXEC constant

None of the CHeMS file are able to run before the _CEXEC directive has been
appropriately declared. If you try to "call" a PHP file directly you'll get
the "Restricted access!" message. That's why there is a check at the begin
of each file which ensures that such constant has been defined - or - it's
effectively CHeMS that is trying to run that file. This is of course, as
you can image, for security reason. The check is like the following:

   defined("_CEXEC") or die ("Restricted access!");

The only file which is able to run CHeMS is the index.php file whic includes
the following declaration:

   // This is CHeMS!
   define("_CEXEC", True);

Into the secondary files (called by index.php) the define() constant return
true and die() is not called at all, leaving the rest of the instructions to
be executed. You should include the above check in all of your PHP files.


. Hello world module

Okay, boring concepts are finished :-) Put your hands into the code.

The following is a ``quick'' example of a basic module which only show a block
with the "Hello world" text.

   /*
    * Hello world module
   */
   function helloworld_main()
   {
      return "<h2>Hello world</h2>"; // Prints "Hello world"
   } /* eof helloworld_main() */

That's all. You have to put it into the "modules/helloworld/helloworld.php"
file and load it from the &quot;usr/config.php&quot; file adding a line like
this:

   modload("helloworld", "left" , "all");

It's quite simple. Now i'll make things interesting by linking this text to a
page generated by the module itself which is shown inside the CHeMS layout.
This is done by adding a new function into the "helloworld.php" file which
generate this page. The suffix "_page" tell CHeMS to show it inside the
layouts:

   /*
    * Hello world module page
   */
   function helloworld_page()
   {
      return "
         <h1>Hello world page</h1>
	 <p>
	    This page has been linked by the <b>hello world</b> module.<br />
	 </p>
      ";
   } /* eof helloworld_page() */

To allow CHeMS to show this page (by calling the helloworld_page() function)
the HTTP GET variable "name" (or at least the BASEMOD option value) must
be set to the module's name "helloworld". The helloworld_main() function have
to be modified as follow:

   /*
    * Hello world module (linked)
   */
   function helloworld_main()
   {
      $link = WEBROOT."?type=mod&amp;modname=helloworld"; // The URI
      return "<h2><a href=$link>Hello world</a></h2>"; // Links "Hello world"
   } /* eof helloworld_main() */

Since the '&' character is illegal in this context the HTML code (&amp;) is
used instead. My suggestion is to copy this code into the relative file and
load it (maybe changing something) in order to familiarize with the system.
To allow per-module style customiziation through the CSS, it's a good idea
to provides a divs hierachy like the following:

   <div id='mod_helloworld".$instpfx."_main' class='chems_module'>
      <div class='chems_module_title'>".@constant("MOD_HELLOWORLD_TITLE$instpfx")."</div>
      <div class='chems_module_body'>

This is not mandatory. There are no strictly required rules to write a
module, though it would be a good idea to be compliant with the examples
shown on this guide.
The "correct" (and complete) version of the helloworld module can be then
write this way:

   defined("_CEXEC") or die ("Restricted access!");

   /*
    * Hello world module ("correct" and linked)
   */

   function helloworld_main()
   {

      $text = "
         <div id='mod_helloworld_main' class='chems_module'>
            <div class='chems_module_title'>".@constant("MOD_HELLOWORLD_TITLE$instpfx")."</div>
            <div class='chems_module_body'>
      ";

      $link = WEBROOT."?type=mod&amp;modname=helloworld"; // The URI
      $text .= "<h2><a href=$link>Hello world</a></h2>"; // Links "Hello world"

      // Close the divs
      $text .= "
            </div> <!-- chems_module_body -->
	 </div> <!-- mod_helloworld_main -->
      ";
   }


. Globals variables

The CHeMS core communicate with the modules through a certain number of
classes which contains informations about configuration, modules commons
information themes, etc. These classes may be accessed by declaring them
as global. They are the following:

   $module	informations about the current module
   $THEME	current theme configuration

For informations about objects contains in each class check directly the
source code, since you also will have to be confident with it.


. Formats operators

The configuration system and options are a great thing for users. You can
change almost all the aspect of CHeMS, from the graphics stuff to the text,
the navigation bar position and much of the behaviours. Sometimes, while
dealing with output text for a specified page or module you may want to
include some informations which change dinamically with the time. An example
is the number of posts into the current category, the current page number and
so forth. Since you can't hardcode these values intothe configuration files
some special value which is replaced by the module may be used instead. Also
you can delegate all the computations to the module replacing the format
operator with the results. This way you can leave the configuration file
quite clean and still provide an highly configurable interface. While
generating the pages, any time one of this special values is encountered, the
module replace it with the respective values generating a diffenent output
code depending on the informations collected. This allow you to provides for
your modules configurations options like the actual MOD_NAVIGATION_BAR_MSG*,
etc. A text string which is handled in such way is called "format operator".
Note that format operators are not real operator so you can't use them in
conditional statements or so but only in normal string in which the value of
the current format operator is replaced, nothing more. Feel free to handle
your operators as real operators writing good but complex PHP code.

The process in which a format operator is converted into its resulting value
is called "expansion". You can use any pattern you like but the %[name] form
is the default used in CHeMS; please, be compliant or propose a better way.

To handle the format operators you can use several ways, routines and
approaches but probably the str_replace() function is the better and easiest
way to do the work. The following example implement a format operator which
represent a random number from 1 to 100 and return the expanded text:

   // Expand the format operator and return
   return str_replace("%[randnum]", 1 + random() % 100, $text);

It's not much useful since you can use directly the random function rather
than a format operator but it's just an example (and anyway in a real context
this leave clean the configuration file). A similar example is the following,
which is taken from the showfiles_stat() function of the "showfiles":

   $text .= str_replace("%[files_tot]", $file_tot, MOD_SHOWFILES_INFO);

This line replace the format operator %[files_tot] with the effective number
of files in the list, getting this value from a function argument ($file_tot,
for instance). Then append the expanded text to the $text variable. A more
complex example is the following, which use several operators and expansions
values:

   // Some code
   [ .. ]

   // Format operators definition
   $FO = array(
      %[fo_one],	// Number one
      %[fo_two],	// Number two
      %[fo_three],	// Number three
   );

   // Format operators expansions
   $FOEXP = array(
      "Number one",	// %[fo_one]
      "Number two",	// %[fo_two]
      "Number three",	// %[fo_three]
   );

   return str_replace($FO, $FOEXP,
      "Among %[fo_one] and %[fo_three] there is %[fo_two]");

This way you can expand a whole collection of format operators by
associating a pair operators/expansions of arrays. For a more dynamic and
complex implementation look at the source code for the "catogories" module
which do the expansion work inside a loop.


. TFB DB API

The Text-file-based database application programming interface (TFB DB API)
is a collection of routines which allow to deal with informations simulating
a very simple database. This API is based on regular files: no SQL queries,
no DB installation, no portability problems. However, there are not all the
benefits of a real database, including performances. But since CHeMS in a
personal helper management system for contents, you cat write your own SQL
API or just handles your module's informations with MySQL or so. You have to
write your web applications, CHeMS don't have to do it for you.

Actually, the only routines implemented (since are the only needed) are:

   cdb_insert()	Add a new record into the specified DB. If the file does
   	        not already exists it is created.

   cdb_return()	Return the whole given record content depending on the ID
   		and a list of mathing values, if any.

   cdb_totals()	Returns the number of totals recond into the given file

Others routines may be implemented in further releases of CHeMS. See the
"src/cdb.php" file for more informations.


. Handling multiple instances

As discussed into the ``Multiple instances'' section of the ''Configuration
and basic usage'' chapter above, the module can be able to handle differents
instances of themself in a different way providing differents options for
each. Though the user configuration side is quite easy to deal with, the
implementation is even easier. You only have to include few lines of PHP code
at the beginning of your module in order to get the identifier which have to
be appended to the end of each directive. This way each instance (represented
by the identifier) have its own configuration directives. The current
instance identifier is stored into the $module class in the "instance"
variable. Supposing to have a module called "testmod", an example code used
to get the identifier is the following:

   global $module; // Module informations

   // Generate the instance postfix
   $instpfx = (isset($module->istance) && $module->instance ? $instpfx = "_".strtoupper($module->instance) : '');

Then you should do something like this in order to get the options values:

   // Store the instance module body
   $body = constant("MOD_TESTMOD_BODY$instpfx");

Once you done it for all of your implemented configuration directives, the
module have the full support for multiple instances provided by CHeMS. If you
only want to learn about the current instance (maybe to disable multiple
instances of a module) use a code as the following:

   global $module; // Module informations

   // Don't allow mutiple instances
   if( $module->instid )
      return CHEMS_MODULE_FAILURE;

NOTE: the modules cannot predict in which order they will be loaded (indeed
      this depends on the order they are placed into the config.php file) so
      you should *never* assume nothing about the module instance ID or if a
      specific module or instance is loaded before or after another.

In any case all modules should explicitally return an error when no multiple
instances have to be handled so as all modules should always be able to load
a default element when nobody has been selected. This also allow to use the
module name as value for the BASEMOD option (only module that provides internal
pages - *_page). A more compact way to ignore multiple instances is to use the
$GLOBALS array without using $module. Doing it just with the following code:

   // No multiple instances allowed
   if( $GLOBALS["module"]->instance )
      return CHEMS_MODULE_FAILURE;

Let see how the things work. While the modules generation phase CHeMS store
a progressive index (starting from zero) from each module to the variable
"instance" of the $module class before this module is loaded. A complete set
of informations for the current module are stored too by getting the module
key/value pairs and putting them into the $module class using the current key
as variable name and sharing the values. E.g. the values for the pair
"a" => "b" is stored into the $module->a variable, that for the pair
"one" => "two" is stored into the $module->one variable and so on. This way
you have the same set of informations for each module but only the current
module values are stored (including unique instance ID $module->instid). Note
that the instance ID change depending on the order the modules are loaded.

Finally, you should know about "null modules" which, since the 0x04 of CHeMS,
are totally ignored. This mean that if a module returns NULL, it's just
ignored by CHeMS as it were not loaded at all.


* Internals

. Design

CHeMS is written with a concept in mind: everything is a module. There are
no features integrated into the CHeMS core. Everything CHeMS is able to do
is implemented through a module (including normal pages and posts). The only
things CHeMS does are the following:

   o Check the loaded modules and

   o provide an unique instance ID for each module which 
     exists *only* for the duration of that module loading.
     Once a module has been successfully loaded the instance
     ID is not available anymore and all informations about
     the module are cleared.

   o Create the XHTML compliant page and put the modules into
     their place depending on the user setting (the arguments
     provided to the modload() routine which, for istance, is
     implemented in "src/functions.php").

Any other thing is implemented by modules, from pages visualization to the
menu blocks which shown pages links, posts links, meta tags, etc. This type
of implementation allow to mantain a core of less than 2-300 effective SLOC.


. Divs hierachy

CHeMS doesn't generate all HTML tags for the whole page. Instead, it provide
the main divs inside of which the modules can put their own divs. To gather
informations about the current module's divs hierachy see the paragraph on
writing modules. The actual divs hierachy of the CHeMS core is the following:

   <body>
      <div id='header'>
         <div class='incol'><!-- Here goes the CHeMS header--></div>
      </div>
      <div id='layout'>
         <div id='main'>
	    <!-- Here goes the menu both (left and right) -->
            <div id='main_page_body'><!-- Here goes the module's page --></div>
            <div class='cleaner'>&nbsp;</div>
	 </div>
      </div>
      <div id='footer'><div class='incol'><p><!-- Here goes the footer --></p></div></div>
   </body>

This way it's possible to handle the layout through the CSS; that's the way
CHeMS works at the moment. Most people think it's not a good idea to make
the layout via CSS but i think it's the most easy and flexible way to do
the things. Else edit the source code is needed in order to change the page
layout and work on the CSS (which is what users should be) it's not enough.
If non empty, the menus adds another div:

   <div id='menu_SIDE'><div class='incol'><!-- Here goes the SIDE menu --></div></div>

Where SIDE is "left" or "right" depending on the menu.
Inside the menu and module's page divs each module can put its own divs
depending on the type of style and customization through CSS it want to
provide. In general, all the modules actually implemented and released
with the CHeMS packages, follow this hierachy:

   <div id='mod_NAME' class='chems_module'>
      <div class='chems_module_title'><!-- Here goes the module's title --></div>
      <div class='chems_module_body'><!-- Here goes the module's body --></div>
   </div>

This way allow full customization for both single or all modules. Also
guarantee that the modules don't make problems by changing the layout
since each module is inside a "jail" of HTML divs generated by the core.


* Conclusions

This guide introduced the main concepts behind CHeMS and how it works. You
should now be able to use, configure end extend it efficiently. New modules
are appreciated and if well written they will be probably included into the
CHeMS main tree, just submit them. Please, before to send any code (modules,
patches, etc.) be sure it works on both PHP version 4 and 5. You should also
care about XHTLM IDs (and friends) dynamic generation which may cause
problems with W3C validation due to cloned ID or with CSS stuff which affects
more than one tag. For this reason you should never use the module instance
name suffix and all the current classes informations provided by CHeMS into
the XHTML tags IDs strings. This why a module may have multiple instances of
itself while the IDs still have an unique name. Keep your code simple but
think about it.


That's all, folks!

=============================================================================