Documentation

Saint documentation comes in three parts:

  1. User Guide (HTML) (PDF): Site administration.
  2. Developer Guide (HTML) (PDF): Site creation.
  3. API Reference (HTML): Full PHPDoc reference to Saint classes and functions.

Saint Developer Guide

Introduction

Saint was designed from the ground up to make life easier for developers. To the end user it is merely a fully functional content management system. To the developer it is also a framework of tools that allow easy creation of custom dynamic-content websites. The second premise of Saint's design is that the person trying to edit content is not always a technical person. Thus the programmer may set restrictions on data in ways not possible in other content management systems, preventing an unintended layout modification.
Saint sites are thus meant to be created by a programmer, deployed and then maintained by a non-technical user. The programmer is given tools to speed development and the end user is given a simple but modern AJAX powered interface for editing content.
This guide is meant to act as a basic tutorial. For detailed information about functions, see the API documentation.

1.1 Installation

Saint is distributed in the form of a compressed archive. Acquire your copy from the Saint website (http://www.saintcms.com/) and extract it to your web root to start. Edit the file “config.php” and enter the database details you wish to use. If you don't have a database already you'll have to create one; check with your web host if you are unsure of how to proceed. Once the config file is saved you will need to set proper permissions on your logs, media and uploads directories; the web server needs to be able to write to them. This can generally be done via FTP, but you may wish to check with your hosting provider if you are not sure of the proper way to set permissions on your server.
Now point your browser to your web location. If you are developing locally, this is probably 127.0.0.1 or “localhost”. If you are developing on a live server you will have been given a URL to use to access your website. After accepting the license agreement you should be presented with a form requesting a username, password and e-mail address for the site administrative account. Enter this information and submit the form to finish the install.

1.2 Your First Website

The Saint install enables a few basic pages linked by menu. These are not the actual Saint interface. They are instead just examples distributed with the system to make development more straightforward. The Saint interface is an overlay which appears in all pages of your site when you are authorized to see it. To access it, navigate to the path “/login”. Enter your administrative username/password and submit the form to continue. Now you will see the Saint menu in the upper right hand corner. If you haven't already read the Saint user guide, now is the time to do so. It will teach you how to use the Saint interface. When you have completed that, return here and move on to the next section.

Themes

As you might expect, editing core files is not necessary (nor advised) to create a custom Saint theme. By default Saint uses files found in the “core” directory. However, when a theme is selected Saint instead relies on a fallback system: First the theme directory is checked, then the core directory.

2.1 Creating a Theme

To create a theme, make a new folder in the “themes” directory. Congratulations! You have made your first Saint theme. To activate it, edit the base config file and change the theme name to match your folder name.

2.2 Editing Your Theme

You may notice that your theme looks exactly like the vanilla theme. This is because Saint checked your theme directory for files, found none, and fell back to the default interface. Let's say you wish to change the navigation bar. In your themes folder, create a new folder called “blocks”. Inside that folder, create another called “navigation”. Copy the file “menu.php” from “core/blocks/navigation” to “themes/yourtheme/blocks/navigation”. Now you can edit the file in your theme directory and the changes will appear when your theme is active.
This idea holds true for any of the blocks, scripts or styles used in Saint. Any of these files found in the active theme directory will override their respective files in the core folder. This allows you to create “minimal” themes which only alter necessary files. The theme directory is where you will store all your site's files.

Labels

The first step to converting your static template to a Saint powered website is to replace all text with labels. Labels are simply areas of text which the system makes editable. They are easy to use. Any place you would normally write plain text, substitute with the following Saint function:
<?php echo Saint::getLabel("labelname","Default text"); ?>
The output will start as your “Default text” argument. This text is stored in the database and editable via the Saint web interface. Content output by this function will be the same on every page. For an example of this, see the text in the menu items. These use site-wide labels.

3.1 Page Labels

At times the need arises to use text that is specific to each page. This can also be accomplished by using the following function instead:
<?php echo $page->getLabel("labelname","Default text"); ?>
By using the running page's getLabel function any changes made to one page will not affect other pages. As such you may design a template for use in multiple pages, each with its own data.
As you may have guessed, you can put the same label in multiple locations by referencing the same name. As outlined above the names would not create a conflict, since the way the “Page” label function works internally is by adding the name of the page to the start of the label. Thus, on a page called “blog”, a page label called “title” becomes “blog/title”. You can use this knowledge to reference page blocks from external locations, simply by requesting their name directly.

3.2 Block Labels

Block labels are just like page labels except they are specific to individual blocks. Here is an example of usage within a repeating block:
<?php echo $block->getLabel("labelname","Default text"); ?>

3.3 WYSIWYG Labels

Normally blocks in Saint are meant to have rigid structure matching each data type. Using them as outlined above the developer can create custom editable content areas which match specific layouts. However, Saint also comes with a popular “What You See Is What You Get” editor for use in situations where that functionality is wanted. The following code will insert a WYSIWYG editable area:
<?php echo Saint::getLabel("content",array('wysiwyg'=>true); ?>
The one argument given is the name of the WYSIWYG block. This attribute can be applied to page and block content labels too. You can see the WYSIWYG block at work in the sample home layout.

Blocks

Blocks are chunks of code which may be included within the site. These are the place to find any HTML templates you wish to edit. They can, and often do, include other blocks within themselves. In the folder named "Layouts" you will find the root blocks called, as you may have guessed, layouts. They are just like any other block with the exception that when creating a page it is only possible to use one of these blocks as the base. Starting from these root blocks an entire page is generated.
In the "Content" directory you will find blocks meant to go in the main content section of your website. This is not enforced by site code but is merely a convention for where to store your templates.
It is possible to create an entire website in Saint by having simple HTML code in the layout files and using them as basic pages. This, as you might imagine, is not an effective use of Saint; but it demonstrates the simplest possible site. Instead, these blocks are meant to contain layout HTML along with the dynamic Saint data models such as labels, images, galleries, slideshows, or repeating blocks.
To include a block within one of your template files, use the following function:
<?php Saint::includeBlock("name"); ?>
Where “name” represents the name of the block you wish to include. This name is relative to the “blocks” directory and does not include the extension of the file. Thus, a file in the /blocks/content directory called “test.php” would have a name of “content/test”. Saint first looks in this base directory for files. If they are not found, it then looks in the same respective directory in the “core” folder. In this fashion, any core file can be overridden by dropping a file of the same name into the root blocks folder. This is referred to as the “user” folder. All your site files will be in the user directories, while all the Saint files will be in the core directory. This keeps your site separate from the Saint code.

4.1 Scripts and Styles

Scripts and styles are included in a similar fashion to blocks. The same rules apply to both the naming convention and the directory precedence. The functions for including these are listed here:
<?php Saint::includeStyle("saint"); ?>
<?php Saint::includeScript("saint"); ?>
They are located in the “styles” and “scripts” directories, respectively. In order to use

4.2 Repeating Blocks

Repeating blocks are the most powerful construct in a dynamic Saint website. Do you have any content that repeats? Virtually all websites do. Blog posts, news items, calendar events, interviews, links... these are all items which should be inserted into repeating blocks. What is the advantage in doing so? Repeating blocks can be added and removed through the site user interface. Let's work with a more concrete example by creating our own test blog.
To include a repeating block we pass an optional array parameter containing arguments. If the parameter “repeat” is set to more than one then the block will automatically repeat. Create a file called “test.php” in the blocks/layouts directory containing the following code:
<?php Saint::includeBlock("content/test",array("repeat"=>4)); ?>
Next, create a file called “test.php” in the blocks/content directory containing the following code:
<h3><?php echo $block->getLabel("title","test title"); ?></h3>
<p><?php echo $block->getLabel("content","test content"); ?></p>
Finally, assign a page to your test layout using the Saint web interface.
At first you should see a note that there are no blocks found matching your criteria. This is because we haven't added any. Start editing the current page and click the “Add New Test” button. You will see editable blocks of text named “title” and “content” with your default values as entered above. You can create any number of fields in this fashion. Labels, WYSIWYG areas, and other blocks can all be placed within repeating blocks.
In this scenario we used the Saint content function getBlockLabel for our text. This means that all the labels will be unique within their blocks. As with page labels, the way this works is by adding the name of the block, along with the block ID, to the front of the label name. The name of the block represents the template used and the number represents the automatically generated ID from the database for this specific instance of the block.

4.2.1 Block Settings

By default repeating blocks will be sorted by their automatically generated database ID. This will work for many types of data, but at times you'll need to change it. In our blog post example above we may wish to add a date setting and seo tags to each post. “Ok,” you think, “It's time to write some SQL.” Not quite. All the block settings in Saint are handled via XML config files. By convention, each repeating block will have its settings in a file of the same name using the xml extension. This is just convention; the entire blocks directory is scanned for all xml files, and all the configuration can be done from a single file if you wish. Following convention, we would create a file called “post.xml” in the blocks/content directory containing the following code:
<?xml version="1.0" encoding="UTF-8"?>
<block>
	<name>content/blog-post</name>
	<setting datatype="datetime">postdate</setting>
	<setting>tags</setting>
</block>
Now after refreshing the page you will be able to edit block settings in the right hand column of the “edit block” interface. You can display these settings within a block template by using the following function:
<?php echo $block->get($setting); ?>
Where $setting represents the name of the setting, such as “postdate”. The most useful feature of settings is that they can be used to filter and sort the repeating blocks.

4.2.2 Block Arguments

Blocks can be passed a number of arguments to configure their inclusion. Let's look at an example based on the Saint blog:
$arguments = array(
	"paging" => true,
	"repeat" => 2,
	"order" => "DESC",
	"orderby" => "postdate",
	"category" => "News",
	"matches" => array("enabled","1"),
);
Saint::includeBlock("blog/post",$arguments);
Let's start from the top. By setting “paging” to true the Saint automatic paging system is enabled. Users will now see a “next” and “previous” button when applicable as well as a listing of pages.
The “repeat” argument sets how many blocks are included. In this example, we have two blog posts per page.
The “order” argument will be either “ASC” or “DESC” and is passed to the database for sorting.
The “orderby” argument must match one of the columns of the block table. There are two built in fields, the auto incremented 'id' and a boolean 'enabled'. Any other field must be added as a block setting. In this case, we are using the block setting “postdate” which is a datetime field representing our posted date.
The “category” argument accepts either a scalar category name or an array of category names to match (Note: This is actually not true at the moment, I've just noticed. I must fix this before release. At the moment it just accepts a single scalar category name).
The “matches” argument accepts either a single array of parameters to match, as shown in the example, or a multidimensional array of parameters as shown below. In addition, each set of parameters accepts an optional third argument defining the type of matching to use.
"matches" => array(
	array("enabled","1"),
	array("postdate","2012-03-13 18:23:45",">"),
),
This would result in the system only displaying posts from a date later than the one given. This field accepts any comparison operator which works with their database. As with the “orderby” argument, all names given must be block setting names.

4.2.3 Multiple Views

The repeating block system is extremely useful for rapid development, but in many cases we don't just want to display the data in one location or in one format. You've created a blog, but now you want a “Latest News” preview box on your front page. You want an RSS feed of your posts. So, open up phpMyAdmin, examine the table generated by Saint for your block, and write up an SQL query to extract the data you need. No, sorry, I got caught up in the old way for a minute. All you have to do is pass Saint an additional argument defining a view template. Have a look at this example:
$arguments['view'] = "blog/rss-item";
Saint::includeBlock("blog/post",$arguments);
It's very similar to the above example, with the block name and $arguments array being the same as before with the addition of the view shown. This new field is the block to use as a template for our data. Put simply, all the “blog/post” blocks matching $arguments will be passed to the “blog/rss-item” template for display. In this way, we can add multiple views of any given block data.

4.3 Saint Blog

As you've likely guessed, the blog system included with Saint is a block with multiple views as described above. If you have any doubts about how fast it is to develop with Saint, have a look at the code for the included blog. All the tedious parts of coding are handled by the Saint framework; the blog code itself merely defines ways in which blog posts differ from standard blocks instead of recreating the functionality from the ground up This is just a small example of the power of Saint. Save yourself time and frustration by utilizing this power in all your new web applications.

Permissions

Permissions in Saint are handled through groups. By default new groups do not have any rights, so you must add them in the core configuration file. This file is “core/config.php” in keeping with the usual Saint convention. In this case both the core and the user versions are loaded but any flags set in the user file will override ones of the same name in the core config file. There are four default groups: administrator, moderator, user, and guest. Say you wanted to add a custom group to the list called “friends” who are able to view the website while you are still building it. You might use the following code:
$saint_group_access = array(
	'friends' => array('maintenance-mode'),
	'administrator' => array([...]),
	[...]
);
After this change, any users you put into the “Friends” category will be able to view the website even when it is flagged for maintenance.
Let's take it a step further. Now you want to give friends the ability to post on your blog. Modify the code like so:
$saint_group_access = array(
	'friends' => array('maintenance-mode','add-blog-post'),
	'administrator' => array([...]),
	[...]
);
We're not quite done yet. Since a blog post is just a standard block, the default permission checked is actually 'add-block'. You'll need to add your own security check in the controller using the following code:
if (Saint::getCurrentUser()->hasPermissionTo('add-blog-post')) {
	// Save post here
} else {
	Saint::logError("User ".Saint::getCurrentUsername() . " attempted to add blog post but was denied access.",__FILE__,__LINE__);
}
Saint::getCurrentUser() returns a model of our logged in user. The Saint_Model_User::hasPermissionTo(“string”) function returns true/false based on whether or not a user of that group is allowed to perform the given task. But wait, you ask, where do I put that code? Let's continue on to the next section to find out.

Controllers

By now you should know enough about Saint for most situations. One thing we haven't covered yet is handling user input in your custom applications. There's no reason that you can't handle it in the traditional way, manipulating data inside of your block templates. If you are building a large application you may wish to improve organization by using the same Model View Controller architecture as Saint. Describing it in full is beyond the scope of this document, but put simply in an MVC system all user input is handled by something called the “controller”. This is, generally and specifically in the case of Saint, accomplished using an object. All controller classes are located inside the “code/Controller” directory. Controllers are subject to the same loading rules as blocks and styles. Thus, in the case of a file existing in both “code/Controller” and “core/code/Controller” the user version will be preferred over the core version.
First you must create a class in the “Controller” directory. The name of the class must match the name of the file in the form of “Saint_Controller_Filename” with no extension. It is case sensitive. Then, add methods to your class which accept your expected input as arguments.
In Saint, the “Page” controller handles page requests. It acts as a router for input, checking the GET and POST variables and calling the appropriate functions located in other controllers. Copy this file from the core directory to your theme code directory before making any changes. Then, using the other code as an example, create a hook to call your own controller's function.

6.1 Controller Security

Security in Saint is handled in two main places. As the controllers are specifically meant to take action in response to user input they are, in essence, the “users” of our website from the system's perspective. They ask the models to manipulate the data. Models trust the controller's intent inherently. Thus, we need to ensure that our controllers only allow appropriate action to be taken by users. Any time you program a controller to perform actions be sure you also use the functions listed in the “Permissions” section and add a check on whether or not the user is allowed to perform the action requested.
Controllers handles all of the “action” type security checks. The other half of Saint security is handled by the models themselves and is outlined in the following section.

Models

Access and manipulation of non-volatile data sources in a MVC system like Saint is the domain of the models. Located in the “code/Model” directory, models are classes that interact with the database. To the rest of the system, a model is representative of an abstract data type. You may view the core model source files and get an idea of how this works, but the general idea is that instead of accessing the data directly from other places you instead call a function offered by the model and use the result. Similarly, instead of changing the data you pass it to the model and have the model do the manipulation.

7.1 Model Security

Protection against straightforward attempts by users to do that which is not allowed in the group access listing is provided by your controllers. However, a second type of attack exists whereby malicious users attempt to trick the system into running a different command than is originally intended. In a PHP/MySQL environment, that type of attack is centered on SQL injection and filesystem manipulation. Any time a model is to access the filesystem or the database using input passed to it the input must first be passed through the Saint sanitization function. This function will return the sanitized string, or false if it fails the test. It accepts a regular expression to match as an optional second argument; several of these are defined in the core Saint config file as constants and used throughout the site. Here is an example using the function:
if ($sname = Saint::sanitize($name,SAINT_REG_NAME)) {
	// Do things here with $sname
} else {
	Saint::logError("Name '$name' is invalid.",__FILE__,__LINE__);
}

7.1.1 Patterns

All names used within the Saint system must pass the built in SAINT_REG_NAME pattern. There are various reasons for this, but the one that is most likely to make people curious will be the restriction on underscores. To put it as simply as possible, Saint names are meant to match the file hierarchy exactly. As such they need to use forward slashes. However, there are limited characters available for use in standards compliant web IDs and slashes aren't one of them. Saint changes all slashes into underscores for web use via the Saint::convertNameToWeb($sname) function, and back using Saint::convertNameFromWeb($sname).
There are four basic patterns defined in the core config file and used through Saint. These are SAINT_REG_NAME, SAINT_REG_ID, SAINT_REG_EMAIL, and SAINT_REG_BOOL. The ID pattern matches positive integers only. The boolean pattern matches 0 or 1, not “true” or “false” (the PHP constants TRUE and FALSE will work, since they represent 1 and 0 respectively). The e-mail pattern will match any valid e-mails. You are free to add your own patterns to the user config file to use in your code, or to use the built in ones available.

Logging

There are three log types in Saint: events, warnings, and errors. They each append new entries to their respective files, while all entries show up in the administrator's web interface log. All of the functions accept the log message as the first argument as well as optional second and third arguments representing the file and line numbers of the code, respectively. Logging can be set to exclude events, both events and warnings, or to be completely disabled by setting SAINT_LOG_LEVEL in the core config file.

8.1 Events

Events are fired in the normal course of activity. They are used to indicate that an activity has occurred. An example of this would be an event firing when saving user data:
Saint::logEvent("Saved info for user '$this->_username'.");

8.2 Warnings

Warnings indicate problems that are not fatal to the running of the program. An example of this would be the warning that is logged when Saint can't find a style that is indicated in one of the templates:
Saint::logWarning("Cannot find style $style.");

8.3 Errors

Errors are problems that stop the function from completing a requested action. This indicates problems that should be fixed as soon as possible. If you see errors that you think are bugs then submit a full report with as many details as possible to bugs@saintcms.com. An example of error log usage is found below:
Saint::logError("Invalid file name: '$name'. ",__FILE__,__LINE__);
For those who are wondering, __FILE__ and __LINE__ are magic constants provided by PHP which return the current file name and current line number at the point of their use. They must be passed to the logging function since running them inside returns the file and line of the log function.