ATutor Developer Documentation

Table of Contents

top

0. Version Considerations

This document is found in ATutor's documentation/ directory and is maintained along with the rest of the code in the code repository. The latest version of this document will always be available in the repository. Versions bundled with ATutor releases are specific to that release. If you are modifying a previous version of ATutor then you should refer to the version of these guidlines as they are available with that specific version.

top

1. Introduction

ATutor, as an open source project, encourages PHP developers to contribute new features. To ensure that newly contributed code is easy to accept and maintain, we must urge you to follow the guidelines we outline below. These rules and recommendations were created to ease the distributed development process.

The latest version of this document can always be found at ATutor.ca.

top

2. Conventions Used in This Document

This section covers the typographical conventions used in this document.

2.1 Typographic Conventions

Constant width

Used for commands and code examples. Example: Use the debug() function to view a variable.

`Constant width surrounded by quotes`

Constant-width font with surrounding quotes is used for filenames and path names. Example: The `vitals.php` file is important.

Square brackets (`[` and `]`)

In syntax descriptions, square brackets (`[` and `]`) are used to indicate optional words or clauses. Not to be confused with the use of square brackets in array definitions. For example, in the following statement, version is optional: ./bundle.sh [version].

Pipe (`|`)

When a syntax element consists of a number of alternatives, the alternatives are separated by pipes (`|`).

Example code is to be used as examples only and not as tested production code. In most cases its usefulness in the context of the example outweighs its correctness as workable code. In other cases the syntax and style used in the example itself are irrelevant and do not follow the coding guidelines outlined below. For example, arrays may be documented using string keys without quoting their value, $_SESSION[prefs], while in practice it is always best to escape the key with quotes: $_SESSION['prefs'].

2.2 Links

All the links in this document open in the current browser. Links that are not obviously to external sites are supplemented with title text. All other links are assumed to be anchors within this document.

2.3 Function Definitions (Prototypes)

The usage of the square brackets (`[` and `]`) around parameters imply that they are optional, in which case the function documentation will then state what the default value for that variable is. Please pay close attention to the return types of functions: If a function is described to return boolean then it will return either TRUE or FALSE and not an integer such as 0 or 1. Optional arguments to functions must always be listed as the last parameters in the list.

returned_type function_name( param_type $param_name [, opt_param_type $opt_param_name])

returned_type

Type of value this function returns. See Types and PHP type comparison tables.

function_name

The function name.

param_type and opt_param_type

The type of the parameter that the function expects. See Types and PHP type comparison tables.

$param_name and $opt_param_name

The names of the parameters as they are used in the function. The $opt_param_name is optional.

top

3. Setup

Please review the ATutor requirements and ensure that your development environment meets the minimum requirements.

3.1 PHP Configuration

If you have a dedicated development environment that doesn't share a web server with other production code, then it is best to use the bundled php.ini-dist configuration file as the default--simply rename it to php.ini. Listed below are the essential configuration options and their recommended value:

safe_mode            = Off
error_reporting      = E_ALL
display_errors       = On
arg_separator.input  = ";&"
register_globals     = Off
magic_quotes_gpc     = Off
magic_quotes_runtime = Off
allow_url_fopen      = On
register_argc_argv   = Off

top

4. Subversion (SVN)

We have adopted Subversion (SVN) in place of the aging CVS, allowing us to open up the development repository while still maintaining control over the core project. Additional information can be found on the Subversion homepage.

4.1 Installing an SVN Client & Checking-Out

To obtain a working copy of ATutor, you need to install an SVN client and do a checkout from our repository of the latest ATutor source code. Checking out the repository creates a copy of it on your local machine with the necessary version control information. The location of the copied files should be web accessible, i.e. a directory under your web server's path.

For windows users, we recommend using TortoiseSVN, which is a feature-rich SVN extension for Windows that supports many of the options of other SVN clients (file browser and filters not being one of them). Once TortoiseSVN has been successfully installed and you've rebooted your computer, go to a working directory where you wish to checkout the ATutor source code. Right-click to pop-up the context menu and select the command "Checkout...".

For repository URL, enter http://atutorsvn.atrc.utoronto.ca/repos/atutor/trunk. If you enter a folder name that does not yet exist, a directory with that name will be created. Press "OK", and the source will be downloaded to your computer.

For non-Windows users, download an appropriate SVN package from the Subversion homepage and follow the installation instructions. These packages use the command-line client. Checking out the most recent ATutor source code can be done with the following command: svn checkout http://atutorsvn.atrc.utoronto.ca/repos/atutor/trunk.

4.2 Installing ATutor From SVN

Before starting the installation process you should create an empty `config.inc.php` file in the `include/` directory: use touch config.inc.php on UNIX. Browse to the location of your checked out files in a web browser and proceed with the ATutor installation instructions. This will set up the database and user accounts for your ATutor system. The resulting ATutor installation will be your developing environment.

4.3 Updating ATutor From SVN

You should periodically perform updates from the repository to make sure you are working with the developers' latest files. To do this with TortoiseSVN, right click on the working folder and select "Update" from the context menu. For command-line svn clients, use: svn update.

Always review the latest SVN SQL upgrade file to ensure your database structure is up-to-date. The file will contain schema changes of the current pre-released source. Example: If the current working source will be version 1.9, then the upgrade file to keep track of will be named atutor_upgrade_x.y.z_to_1.9.sql, where x.y.z is the version of the currently available stable release.

4.4 Keywords

Until Subversion supports server wide configuration options, the svn:keyword="Id" option will have to be set on a file-by-file basis via the client. After the keyword property has been set for the given file, add the line // $ I d (without the spaces) at the top of the file directly below the main comment block to identify the author, date and time of the last commit.

After the file has been added and committed to the repository the keyword will be expanded into // $Id: guidelines.html 3071 2005-01-12 21:53:13Z joel $. It is helpful to read that line when first opening a file as it lets you know if you were the last person to edit that file and if not, to look out for possible changes.

To set svn:keyword="Id" on a file using TortoiseSVN, right-click on a file, select "Properties" then select the "TortoiseSVN" tab, enter svn:keywords in the drop-down and Id in the text box then use the "Set" button.

top

5. Communication

All communication between developers should occur in the mailing list or the developer forum. Please try to keep discussions public including any feature proposals.

top

6. Patches

Patches should be applied using the UNIX patch command. Make sure your `.patch` or `.diff` files will be compatible or send explicit instructions on how to apply your changes. Always specify what release or source date you are patching against. We prefer unified diffs. Diffs can be sent via the mailing list.

top

7. Editor Tips

We use EditPlus, but you can use whichever editor and settings you feel comfortable with. The most important part when editing is to ensure that tabs meet the coding guidelines on indentation.

A few desirable features for a good text editor are listed below:

top

8. Proposed Features

The Proposed Features page lists features which have been requested by the ATutor community. ATutor.ca members can vote on features to establish a priority, while potential developers may then assign themselves to tasks. New feature requests should be posted to the ATutor Feature Requests forum.

top

9. Bug Tracking

Please report bugs to the ATutor Bug Reports forum. Be sure to indicate the code version being used, such as a release candidate, stable release, nightly build, or SVN checkout, etc. Also be sure to describe the details of the system that ATutor is being developed or tested on, such as the operating system, web server and version, PHP version, etc.

top

10. Creating Bundles

The file `bundle.sh` is located in a directory above `docs` and is used for creating bundles from the working `docs` directory. The Shell script must be run on UNIX and will retrieve the latest version of the language from the database, remove the `cvs_development.inc.php` file, disable debugging, and lastly create a .tar.gz file. Usage:

./bundle.sh [version_number]

Note that you will need execute permissions on the script to use it, and if it isn't in your PATH then you will have to prefix it with a ./. The optional version_number argument will be used for suffixing onto the file name. For example, a version number of 1.8RC1 will generate a file named ATutor-1.8RC1.tar.gz.

top

11. Writing Portable Code

When writing your PHP code please try to use functions that exist since (the minimum requirement) PHP version 4.2.0. If you have to use a function that only exists in later versions of PHP, provide an alternative for older versions. To check if the function is available use either version_compare(phpversion(), $min_version) or function_exists($function_name). For example, to make use of file_get_contents(), which is only available in PHP 4.3.0 and later, use the following:

if (version_compare(phpversion(), '4.3.0') < 0) {
    function file_get_contents($filename) {
        $fd = @fopen($filename, 'rb');
        if ($fd === false) {
            $content = false;
        } else {
            $content = @fread($fd, filesize($filename));
            @fclose($fd);
        }
        return $content;
    }
}

Code has to work on both Windows and UNIX. You should never use exec() or system(). In most cases we prefer to write code that works on both systems as is, without the need for if-statements that check for the operating system, since duplicating the functionality twice (once for each operating system) can be a source of bugs. Review the PHP Configuration section for details on how best to set-up your development environment.

top

12. Coding Style

This section should help those who would like to modify or add code. Anyone who wishes to contribute code must adhere to these guidelines or the code may not be accepted. Please try to write code that is easy to read and maintain with appropriate comments as needed. Correctness and efficiency are easier to certify if code is simple to read and understand.

12.1 Indentation

The importance of indentation for code organization cannot be exaggerated enough. Although indentation is not mandatory in PHP, it is a powerful visual organization tool that should consistently be applied to code.

Internally, we have used hard tabs as we all use the same editor, but we may decide to move to soft tabs in the future. Hard tabs are regular tabs while soft tabs are not really tabs at all; each soft tab is actually represented by a certain number of regular spaces. The benefit of using soft tabs is that they always appear the same, regardless of the editor's tab-spacing. With soft tabs set and enforced, it is easy to maintain consistent indentation and whitespace treatment throughout code. When hard tabs are used, especially if there are multiple developers using different editors, it is easy for mixed levels of indentation to be introduced, confusing the code's layout.

12.2 Line Length

Split the long lines into multiple lines:

if (($month = 'jan') || ($month = 'feb') || ($month = 'mar') || ($month = 'apr')) {
    return 1;
}

You can indent the second line to signify the association with the upper. For particularly long lines, you can indent and align every condition:

if (($month = 'jan') || 
    ($month = 'feb') || 
    ($month = 'mar') || 
    ($month = 'apr')) {

    return 1;
}

This methodology works equally well for function parameters:

echo format_content($content_row['text'], 
                    $content_row['formatting'], 
                    $glossary,
                    $indent);

12.3 Using Whitespace

Whitespace can be used to provide and reinforce logical structure in the code. For example, it can be effectively used to group assignments and show associations. The following example is poorly formatted and difficult to read:

$password = 'mypassword';
$website_url = 'http://atutor.ca';
$first_name = 'Joel';
$last_name = 'Kronenberg';

But this code block can be improved by using whitespace to logically group related assignments together and align them on the equal sign (=):

$pet_type    = 'mypassword';
$website_url = 'http://atutor.ca';
$first_name  = 'Joel';
$last_name   = 'Kronenberg';

12.4 SQL Guidelines

Similar formatting and layout rules applied to PHP can be applied to SQL queries as well. SQL queries, especially in database systems that support complex subqueries, can become convoluted. As with PHP code, whitespace and line breaks should be used in SQL code as needed. Consider the following:

select employees.first_name, employees.last_name from 
               employees where employees.vacation_time > 0 order by employees.last_name";

This is a simple query, but it is poorly organized. Its organization can be improved in a number of ways, including the following:

SELECT   S.first_name, S.last_name 
FROM     students S
WHERE    S.email = '' 
ORDER BY S.last_name";

12.5 SQL/99 Joins

ANSI SQL/99 features ANSI compliant joins. There are several advantages in using this new syntax, one of which is the separation of the JOIN condition from the WHERE clause.

SELECT	M.email, M.login 
FROM	members M, forums_subscriptions S 
WHERE	S.member_id=M.member_id 
AND     M.email <> ''
SQL/99 makes a clear distinction between the fields in the JOIN condition and the WHERE clause:
SELECT	M.email, M.login
FROM	members M
JOIN	forums_subscriptions S USING (member_id)
WHERE	M.email <> ''

12.6 Control Flow Constructs

12.7 Commenting

Avoid using Shell/Perl-style (## this is a comment) comments entirely. Use C-style comments (/* ... */) for large comment blocks and C++-style comments (// ...) for single-line comments only:

/* This is a comment block
 * it is used for describing
 * the code below.
 */
...
// this is a single line comment

Please, document while you code. See phpdoc, like javadoc, for how to document functions, classes, methods, and variables. Coding is often hurried, but it will save a lot of time in the end to do this type of documenting! It looks like this:

   /**
   * what the function does in one line.
   * more detailed description on 0-n lines, if needed.
   * @access  [public|static|pseudostatic]
   * @param   [string|int|double|bool|array|object|mixed] $paramName1 desc
   * @param   [string|int|double|bool|array|object|mixed] $paramName2 desc
   *  ...
   * @param   [string|int|double|bool|array|object|mixed] $paramNameN desc
   * @return  datatype  description
   * @throws  not until PHP 5
   * @see     some_function()
   * @todo    description
   * @since   ATutor version, PHP version   (comma separated list)
   * @status  stable|experimental           (if not set then considered stable)
   * @pattern singleton|factory|mvc|observer|facade|...
   * @author  description                   (comma separated list)
   */
   function something() {
   }
   
Note that the description should be given as plain text not HTML. The @pattern singleton means that the constructor returns a reference to an already existing instance, if there is one.

12.8 Naming Conventions

top

13. Directory Structure

The following is a short explanation of the important components of the ATutor directory structure.

13.1 Directories

`acollab/`
This directory contains files related to ACollab connectivity. These files are necessary to allow ATutor to link into the ACollab system.
`admin/`
This directory contains files used for the administration area (when a user logs in as an administrator). This includes files for system statistics, instructor requests, management of users, courses, categories and languages, and server configuration.
`editor/`
This directory contains files used by a course instructor (or privileged user) to edit course content such as the glossary, course content, forums, announcements, and polls.
`include/`
This directory contains files that are required or included into other files.
`include/classes/`
This directory contains classes, essential to certain ATutor functions, such as the phpMailer, XML, Savant templating, and content management classes.
`include/html/`
This directory contains files that output HTML, usually displayed on (included into) multiple pages.
`include/lib/`
This directory contains library files that hold functions and constants used throughout ATutor code.
`install/include/`
This directory contains files used during the installation process, including each step of the fresh install and upgrade processes.
`install/db/`
This directory contains the SQL files necessary to set up or upgrade the ATutor database.
`jscripts/`
This directory contains all JavaScript files.
`themes/`
This directory contains the different themes installed on an ATutor system, each with its own subdirectory.

13.2 Files

`include/config.inc.php`
This file is created during installation and contains specific configuration information for an ATutor system.
`include/vitals.inc.php`
This file is included by every directly accessible page. It connects to the database, initiates the user session, includes common libraries and constants, and defines frequently used functions.
`include/cvs_development.inc.php`
This file is used to connect to the development language database. Renaming the file will force your system to use the languages available locally.
`themes/themes_readme.txt`
This file contains detailed information on how to create and install a theme.
`include/header.inc.php`
This file outputs the page's header using the correct template and theme.
`include/html/feedback.inc.php`
This file outputs a feedback, error, help, or informative message from the given set variables. See Error and Feedback Messages.
`include/html/footer.inc.php`
This file outputs the page's footer using the correct template and theme.
top

14. Database Structure

A database model diagram (153 KB GIF) created from the ATutor 1.4.1 database schema is available.

top

15. Localisation

All language terms and phrases are stored in the ATutor database. See the _AT() function for details on displaying text. There are three tables that are used for managing languages, their roles are as follows:

`language_pages`
This table is used to cross reference language terms with pages. It allows selecting, via a JOIN, only the terms needed for a particular page. The JOIN may be slow at first but once the result is cached, subsequent calls are many times faster such that only the language needed for a particular page is restored from cache.
`language_text`
This table holds all of the text for an ATutor installation.
`languages`
This table holds the list of all available languages on the system and their attributes.

15.1 Adding & Editing Language

Please see the HowTo Course for more details on translating a language within ATutor.

top

16. Error and Feedback Messages

All messages are handled using the Message class. The main purpose of the Message class is to encapsulate the functionality of tracking and managing various message types during a session by providing a nice layer of abstraction between you and the interface to $_SESSION, where the messages are stored.

At the moment five types of messages are supported:

Error
Messages reflecting negative feedback to the user, indicating issues that need resolving or addressing.
Feedback
Messages reflecting positive feedback, aknowledging a users action was successfull.
Warning
Messages warning the user of a possible action with undesireable effects.
Help
Messages with helpful information about the current page.
Info
Messages with useful information.
Confirmation
Messages requiring a confirmation in order to execute an action.

Please note that using the old method of passing messages is not supported anymore.

Messages can be passed between pages and can be accessed at any time, without any time restriction other than a session timeout.

16.1 Internals

Essentially the internals of the class are divided into two segments, a section responsible for printing graphics via Savant templates and another that manages the storage of Messages.

Tracking messages is accomplished by storing message codes and their optional arguments associatively in $_SESSION. Printing messages is accomplished via Savant and built in templates which can be found in `templates/`.

The relational tracking structure is organized in the following manner inside $_SESSION in no particular order.

Messages are automaticaaly purged from $_SESSION following an appropriate print command.

16.2 Adding Messages

$msg->add{Error|Warning|Info|Feedback|Help}($code);

$code is a String of a language _msgs code or an array with element 0 being the language _msgs code followed by optional arguments. Refer to the language_text table in the database.

Important: One important thing to note is that $code must be stripped of the prefix for that type of message. By prefix it is meant AT_[code_type]_. For example:

There are two ways of adding messages: a single code or a code with an array fo arguments. You can mix-and-match, a combination of both is supported even for the same code. Below is description of the formats:

Adding single code
$msg->addHelp('FILE_EXPORTABLE');

OR

Adding array with arguments
$f = array('FILE_EXPORTABLE', 'arg', 'arg2', ...);
$msg->addHelp($f);

A nice feature implemented is that you do not have to provide all the arguments for a particular code at one time. Subsequent adding of the same code will just append the argument. This allows for greater manipulative flexibility in your source, without writing redundant code. Also note that encoding Feedback codes is no longer necessary for redirection.

Example 1:

$feedback=array('FORUM_ADDED', 'ac_access_groups');
$msg->addFeedback($feedback);

// Before we print lets another another one to the same code
$feedback2=array('FORUM_ADDED', 'about_atutor_help_text');
$msg->addFeedback($feedback2);

// No need to url_encode the code
$filename = 'archive.zip';
$f = array('FILE_UPLOADED_ZIP', $file_name);
$msg->addFeedback($f);

Snapshot of a portion of $_SESSION as a result:

	[feedback] => Array
                (
                    [AT_FEEDBACK_FORUM_ADDED] => Array
                        (
                            [0] => AT_FEEDBACK_FORUM_ADDED
                            [1] => ac_access_groups
                            [2] => about_atutor_help_text
                        )
                        
                    [AT_FEEDBACK_FILE_UPLOADED_ZIP] => Array
                        (
                            [0] => AT_FEEDBACK_FILE_UPLOADED_ZIP
                            [1] => archive.zip
                        )


                )
	...

header('Location: file_manager.php');
exit;

16.3 Printing Messages

$msg->print{Errors|Warnings|Infos|Feedbacks|Helps|All}($optional);

Each will dump all the corresponding tracked messages of that type onto the page at that given line with appropriate graphics defined by its templates file.

printAll() allows all Messages of all types to be dumped immediatley.

One thing to remember is that once a type of Message is printed all tracked data relating to that type is gone. There is no need to worry about purging messages from $_SESSION. The class manages this.

Notice $optional as the argument to this function. This allows you to shortcut the process of adding and printing Message's in one go. For example, suppose you want to add a Message and print it right away. Thus, you pass as an argument ANY argument that you would pass when adding a Message of that type. Essentially, two lines of code are accomplished in one.

Example:
	$msg->addError('MAX_ATTEMPTS');
	$msg->printErrors();
	
	can also be accomplished as:
	
	$msg->printErrors('MAX_ATTEMPTS');

Printing String inside Feedback style box

printNoLookup($str);

Print $str inside a Feedback Message type style box. Performs no dialog with $_SESSION or any language mappings in the language_text DB table. Strictly used in /resources/links/index.php for compatibility.

Checking for existance of specific Message type

contains{Errors|Warnings|Feedbacks|Helps|Infos}();

Returns true if the type of Message is being tracked and contains some kind of data. Useful for branching conditions in knowning when to print a Message or not. Otherwise returns false.

Manually Deleting a specific Message from storage

delete{Error|Warning|Feedback|Help|Info}($code);

Will delete anything related to $code from $_SESSION

Example:
	$msg->deleteFeedback('CANCELLED');

Example Code


...

require_once(AT_INCLUDE_PATH . '/classes/Message/Message.class.php');

global $savant;

$msg = new Message($savant); 

$msg->addError('FORUM_NOT_FOUND');
$msg->addWarning('SAVE_YOUR_WORK');
$msg->addInfo('NO_SEARCH_RESULTS');
$msg->addFeedback('FORUM_ADDED');

/* State of relevant section of $_SESSION at this point 
[message] => Array
        (
            [error] => Array
                (
                    [AT_ERROR_FORUM_NOT_FOUND] => AT_ERROR_FORUM_NOT_FOUND
                )

            [warning] => Array
                (
                    [AT_WARNING_SAVE_YOUR_WORK] => AT_WARNING_SAVE_YOUR_WORK
                )

            [info] => Array
                (
                    [AT_INFOS_NO_SEARCH_RESULTS] => AT_INFOS_NO_SEARCH_RESULTS
                )

            [feedback] => Array
                (
                    [AT_FEEDBACK_FORUM_ADDED] => AT_FEEDBACK_FORUM_ADDED
                )

        )
*/

// Now print them
$msg->printErrors();
$msg->printWarnings();
$msg->printInfos();
$msg->printFeedbacks();

/* State of relevant section of $_SESSION at this point
 [message] => Array
        (
        )
 */

// Let's add an array of arguments
$feedback=array('FORUM_ADDED', 'ac_access_groups');
$msg->addFeedback($feedback);

// Before we print lets another another one to the same code
$feedback2=array('FORUM_ADDED', 'about_atutor_help_text');
$msg->addFeedback($feedback2);

$msg->addHelp('DEMO_HELP2');

$help=array('DEMO_HELP2', $_my_uri);
$msg->addHelp($help);

$help2=array('ADD_TEST', $_my_uri);
$msg->addHelp($help2);

// No need to url_encode the code
$filename = 'archive.zip';
$f = array('FILE_UPLOADED_ZIP', $file_name);
$msg->addFeedback($f);

/* State of relevant section of $_SESSION at this point. Notice the second addFeddback call above
 * had its arguments appended

 [message] => Array
        (
            [feedback] => Array
                (
                    [AT_FEEDBACK_FORUM_ADDED] => Array
                        (
                            [0] => AT_FEEDBACK_FORUM_ADDED
                            [1] => ac_access_groups
                            [2] => about_atutor_help_text
                        )
                        
                    [AT_FEEDBACK_FILE_UPLOADED_ZIP] => Array
                        (
                            [0] => AT_FEEDBACK_FILE_UPLOADED_ZIP
                            [1] => archive.zip
                        )

                )

            [help] => Array
                (
                    [AT_HELP_DEMO_HELP2] => Array
                        (
                            [0] => AT_HELP_DEMO_HELP2
                            [1] => /~Jay/docs/index.php?
                        )

                    [AT_HELP_ADD_TEST] => Array
                        (
                            [0] => AT_HELP_ADD_TEST
                            [1] => /~Jay/docs/index.php?
                        )

                )

        }
*/

$msg->printAll();

/* State of relevant section of $_SESSION at this point
 [message] => Array
        (
        )
 */
 
 ...
top

17. Useful Variables

Most of the variables documented here are required for most pages to function correctly. constant variables, although not explicitly declared as constants, should be considered as such, and not altered.

17.1 $db

Description

constant resource $db

$db is the main database handler. Use it to connect to the ATutor database.

Location

`include/vitals.inc.php`

17.2 $addslashes

See $addslashes().

17.3 $_base_href

Description

constant string $_base_href

The full URL to ATutor's base installation. Supports both regular and SSL protocols. Example: http://myserver.org/files/ATutor/.

Location

`include/lib/constants.inc.php`

17.4 $_base_path

Description

constant string $_base_path

The full absolute path to ATutor's base installation. Example: /files/ATutor/.

Location

`include/lib/constants.inc.php`

17.5 $_user_location

Description

constant $_user_location

$_user_location can be one of five values: `public`, `admin`, `users`, `prog` or empty. This variable must be set before requiring `vitals.inc.php`, and specifies what kind of general user authentication the page declaring it needs.

`public` pages can be viewed by any user, signed-in as a member or not. `admin` pages (those in the `admin/` directory) can only be viewed by the administrator. `users` pages (those in the `users/` directory) can only be viewed by logged in members. If $_user_location is empty, it is assumed the page can only be accessed when a user is signed-in and viewing a course. `prog` is reserved for the pop-up window displaying the progress bar.

This variable was added as a way of specifying which template to use (public, admin, or member). Its role as a way of authenticating is not thoroughly established.

Location

Declared on every page that is directly accessible.

17.6 $_rel_url

Description

constant string $_rel_url

The absolute path and file name relative to ATutor's base installation. If ATutor was installed in http://myserver.org/files/ATutor/, the $_rel_url of the Site-Map page, for example, would evaluate to /tools/sitemap/index.php.

This URL will always be the same for a given page, regardless of the location or path of an installation. This variable was added as a way of standardising the `page` value in the `lang_base_pages` table.

Location

`include/lib/constants.inc.php`

17.7 $_my_uri

Description

constant string $_my_uri

The full path and file name to the current page in a format that is ready to accept additional URL arguments. The argument separator will be defined as SEP. For example, if the current URL is http://myserver.org/index.php?cid=806;disable=PREF_MENU;menu_jump=2, then $_my_uri would be /index.php?cid=806;.

So, $_my_uri is the URL to the current page without the temporary switch arguments. The following URL arguments are removed: enable, disable, expand, menu_jump, g, collapse, f, e, save, and lang.

Location

`include/lib/vitals.inc.php`

17.8 $contentManager

Description

constant ContentManager $contentManager

The $contentManager object provides access to methods for operating on content. All access to the `content` table should be done through this object.

Locations

`include/vitals.inc.php`
`include/classes/ContentManager.class.php`

17.9 $_section

Description

array $_section

This variable is a two-dimensional array used to display a page's breadcrumbs. The first index identifies the page starting from 0 such that $_section[0] defines the first page in the hierarchy, $_section[1] the second, and so on. The second index is used to assign that page's properties, defined as follows: index 0 is the page title, and index 1 is the URL. This variable must be defined before the `header.inc.php file is required.

The URL for the last page (i.e.. the current page) is optional.

Example 1

To assign the path to the site-map:

// the Site-Map is a sub-page of the Tools page, hence we define the path:

$_section[0][0] = _AT('tools');              // the Tools' page title
$_section[0][1] = 'tools/';                  // the Tools' page URL
$_section[1][0] = _AT('sitemap');            // the Site-Map's page title
$_section[1][1] = 'tools/sitemap/index.php'; // the Site-Map's page URL

Location

Declared on every page that is directly accessible.

top

18. Useful Functions

The functions listed below provide vital functionality for ATutor pages. Developers will most likely end up using most, if not all, of the functions below. Please review the Function Definitions (Prototypes) section for an explanation of the syntax being used. Additional javadoc comments can be found with each function's definition.

18.1 authenticate()

authenticate() -- Authenticates the current user against a specified privilege.

Description

mixed authenticate( integer $privilege [, boolean $check] )

Authenticates the current user against $privilege. If $check is AT_PRIV_RETURN then the function will return the status of the authentication with TRUE meaning the user has been successfully authenticated or FALSE otherwise. With $check set to FALSE (default), the function will call exit to abort the script if the user cannot be authenticated and return TRUE otherwise.

The instructor user will always return TRUE.

$privilege is set to one of the constants defined in `include/lib/constants.inc.php`.

Please use only AT_PRIV_RETURN or FALSE as possible values for $check as additional options may be added and the value of the constant changed.

Location

`include/vitals.inc.php`

Example 1

To authenticate an entire page using the announcements management privilege:

define('AT_INCLUDE_PATH', '../include/');
require (AT_INCLUDE_PATH . 'vitals.inc.php');
/**
/* exit if the user cannot be authenticated
 * otherwise continue loading the page.
 */
authenticate(AT_PRIV_ANNOUNCEMENTS);

Example 2

To authenticate a block of code using the forums management privilege:

if (authenticate(AT_PRIV_FORUMS, AT_PRIV_RETURN)) {
    // ... this user has been authenticated
}

18.2 _AT()

_AT() -- Returns translated terms.

Description

string _AT( string $term [, string $argument1 [, string $argument2 ...]] )

This function returns a translated version of $term based on the user's current language preference as defined in $_SESSION[lang]. If $term cannot be found in the language database, it will return `[ $term ]` to signify that it was not found.

Terms may require supplements in the form of additional arguments (see example 2). A term may require zero or more arguments. If a term requires arguments, then they must all be provided; no argument can be left out.

Location

`include/lib/output.inc.php`

Example 1

Printing a single term:

/* echo a translated version of the 'tools' string.
 * i.e. 'Tools' in English, 'Outils' in French, etc..
 */
 $_SESSION['lang'] = 'en';
echo '<h2>' . _AT('tools') . '</h2>';

 $_SESSION['lang'] = 'fr';
echo '<h2>' . _AT('tools') . '</h2>';

Result:

<h2>Tools</h2>
<h2>Outils</h2>

Example 2

Printing a phrase with arguments:

$username = 'Jon';
echo _AT('welcome_message', $username);

Result:

Hello, Jon. Welcome back.

18.3 AT_print()

AT_print() -- Transforms and formats user data for printing.

Description

string AT_print( string $input, string $field_name [, boolean $runtime_html] )

This function returns a transformed version of $input based on the rules specified by $field_name. $input is assumed to originate from the database, but it may be generalised in the future.

$field_name is the unique name of the $input field in the form of table_name.field_name. The formatting options for the given field are defined in `include/lib/constants.inc.php`. If $field_name is not a valid option as defined in the constants file then the function will return $input unchanged.

The boolean $runtime_html is used by fields which have an optional HTML formatting field. $runtime_html should be the associated HTML formatting field for that data. If set to FALSE then HTML elements will be escaped from $input and new line characters converted to <br />s.

No data from the database should be printed without passing it through this function first.

Location

`include/lib/output.inc.php`

Example 1

Printing a field where HTML is not allowed:

$username = 'my_name<b>_is';
$value    = AT_print($username, 'members.login'); // escape the '<b>' tag
echo $value

Result:

my_name<b>_is

18.4 AT_date()

AT_date() -- Returns a localised version of a date.

Description

string AT_date( [string $format [, integer $timestamp [, integer $format_type]]] )

This function returns the string representation of the given $timestamp as transformed by $format. Uses the same options as PHP's date() function, but requires a % in front of each argument. If $timestamp is not specified, then the current time will be used.

$format_type specifies the type of time stamp being provided. Available types are defined in `include/lib/constants.inc.php`. Possible options are:

AT_DATE_MYSQL_DATETIME
The default. Format YYYY-MM-DD HH:MM:SS.
AT_DATE_MYSQL_TIMESTAMP_14
Format YYYYMMDDHHMMSS.
AT_DATE_UNIX_TIMESTAMP
A regular UNIX time stamp; seconds since epoch.
AT_DATE_INDEX_VALUE
A special case specifying that only the single value of $format should be returned. The index into a specified date array. Only available for the following date options: %D, %l, %F, %M.

The following arguments are language dependent:

%D
A three-letter textual representation of a day, Mon through Sun
%F
A full textual representation of a month, January through December
%l (lowercase 'L')
A full textual representation of the day of the week, Monday through Sunday
%M
A three-letter textual representation of a month, Jan through Dec

The following arguments are not yet supported to be language dependent, but may be in the future:

%S
English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with %j
%a
Lowercase Ante meridiem and Post meridiem am or pm
%A
Uppercase Ante meridiem and Post meridiem AM or PM

In most (soon to be all) cases, $format will be specified using a call to _AT() to retrieve the correct date format for that language. See Example 2 below.

Location

`include/lib/output.inc.php`

Example 1

Returning a specified date using a UNIX time stamp:

$time = mktime(0, 0, 0, 7, 14, 2004);
echo AT_Date('%l %F %j, %Y', $time, AT_DATE_UNIX_TIMESTAMP);

Result:

Wednesday July 14, 2004

Example 2

Returning a specified date using a UNIX time stamp that is also language dependent:

$time = mktime(0, 0, 0, 7, 14, 2004);

$_SESSION['lang'] = 'en';
echo AT_Date(_AT('announcement_date_format'), $time, AT_DATE_UNIX_TIMESTAMP);

echo '<br />';
$_SESSION['lang'] = 'fr';
echo AT_Date(_AT('announcement_date_format'), $time, AT_DATE_UNIX_TIMESTAMP);

Result:

Wednesday July 14, 2004
mercredi, 14 juillet 2004

Example 3

Returning a single month name:

$_SESSION['lang'] = 'fr';
The second month in French is: <?php echo AT_date('%F', 2, AT_DATE_INDEX_VALUE) ?>

Result:

The second month in French is: février

18.5 $addslashes()

$addslashes() -- Quotes a string with slashes.

Description

string $addslashes( string $str )

If get_magic_quotes_gpc is disabled, then this variable function maps onto addslashes(), otherwise it maps onto my_add_null_slashes() which simply returns the input $str unchanged.

Location

`include/vitals.inc.php`

Example 1

With magic_quotes_gpc enabled:

$str = "What's going on?";

// prints magic_quotes_gpc: 1
echo 'magic_quotes_gpc: ' . get_magic_quotes_gpc();

// maps to my_add_null_slashes(). prints What\'s going on? [correct]
echo $addslashes($str);

// prints What\\\'s going on? [wrong]
echo addslashes($str);

Example 2

With magic_quotes_gpc disabled:

$str = "What's going on?";

// prints magic_quotes_gpc: 0
echo 'magic_quotes_gpc: ' . get_magic_quotes_gpc();

// maps to addslashes(). prints What\'s going on? [correct]
echo $addslashes($str);

// prints What\'s going on? [correct]
echo addslashes($str);

18.6 debug()

debug() -- Outputs a variable.

Description

void debug( mixed $var [, string $title] )

This function is used for printing variables for debugging. $var can be of any type. The output is nicely formatted and easy to read. debug() will not output anything if the constant AT_DEVEL evaluates to FALSE.

$title is available to label the debugging box for distinguishing it from other debugging boxes on the same page.

Location

`include/vitals.inc.php`

Example 1

Viewing the contents of an array:

$my_array = array('apple' => 'green', 4 => 'something');
debug($my_array, 'my_array');

Result:

    my_array
Array
(
    [apple] => green
    [4] => something
)

18.7 get_login()

get_login() -- Returns the login name of a member.

Description

string get_login( integer $id )

Returns the login name of the member whose ID is $id. There is no error handling.

Location

`include/vitals.inc.php`

18.8 urlencode_feedback()

urlencode_feedback() -- Encodes a feedback code.

Description

mixed urlencode_feedback( mixed $f )

This function returns a URL safe encoding of a feedback code. Its purpose is to encode the feedback into the URL so that the page being redirected to will then output the feedback. $f may be an array of feedback codes, where additionally, each feedback code may be an array consisting of supplementary arguments. If $f is an array then the return value will be its string representation, otherwise the function will return $f unchanged.

The way feedback is implemented may change in the future, so it is best to use this function even if the feedback code is not an array.

Location

`include/vitals.inc.php`

Example 1

To encode a feedback array:

$f[] = array(AT_FEEDBACK_FILE_UPLOADED_ZIP, $file_name);

header('Location: file_manager.php?f='.urlencode_feedback($f));
exit;

top

19. Useful Constants

These constants are part of the vital functionality of ATutor.

19.1 AT_INCLUDE_PATH

Description

The AT_INCLUDE_PATH must be defined before you require or include any files. The constant defines the relative path to the `include/` directory. For security reasons no file should ever be called-in without using this constant!

Example 1

Requiring the vitals file from the tools page:

define('AT_INCLUDE_PATH', '../include/');
require (AT_INCLUDE_PATH . 'vitals.inc.php');

Location

Declared on every page that is directly accessible.

19.2 SEP

Description

For XHTML compliance, we have created this constant to use when applying variables to URL arguments. The constant is one of the values defined by PHP's arg_separator.input, with a preference for the semi-colon (`;`), if available, over the ampersand (`&`).

Example 1

Printing a dynamic link:

$arg1 = 'one';
$arg2 = 'two';

echo "SEP is ".SEP."\n";
echo '<a href="index.php?arg1=' . $arg1 . SEP . 'arg2=' . $arg2 . '">link</a>';

Result:

SEP is ;
<a href="index.php?arg1=one;arg2=two">link</a>

Location

`include/lib/constants.inc.php`

19.3 AT_DEVEL

Description

Enables or disables usage of the debug() function.

Location

`include/vitals.inc.php`

19.4 TABLE_PREFIX

Description

The TABLE_PREFIX constant holds the prefix to the ATutor database tables. It is needed when creating SQL queries.

Location

`include/config.inc.php`

19.5 VERSION

Description

The version number of this ATutor installation.

Location

`include/lib/constants.inc.php`

top

20. Install & Upgrade Scripts

Installing or upgrading ATutor is done with the scripts found in the `install/` directory. Two files in particular control the installation or upgrading flow and are appropriately named `install.php` and `upgrade.php`. For actual documentation on installing or upgrading please see ATutor's official documentation.

The `install/` directory contains two other subdirectories that are used during the installation or upgrade process. The `install/db/` directory contains database schema files and are clearly labeled. The `install/include/` directory contains scripts that are common to both processes and labeled according to their order in either process.

20.1 Install Script

The `install.php` script requires each step as it's needed as the $step counter variable is incremented. To add or edit a step, edit the `install.php` file.

20.2 Upgrade Script

The `upgrade.php` script works exactly the same as the install script does, but requires different files (step prefixed with a 'u'). To upgrade the database schema an SQL file named `atutor_upgrade_from_to_to.sql` must be created, where from is the exact version of the previous ATutor version, and to is the next stable version.

top

21. Accessibility

Part of ATutor's philosophy is to be "designed with accessibility and adaptability in mind", we advise you to consider carefully the practices outlined on the following sites:

top

22. Validation

Please use the W3C Markup Validation Service, a free service, to check your pages for XHTML conformance, W3C Recommendations and other standards.

top

23. Sample Script

The following is sample code that shows the general flow of an ATutor script. The example shows how you may use some of the variables and functions available to you. Some scripts may not need all the variables and functions used below.

<?php
// 0. insert the SVN keywords
// $Id: guidelines.html 1275 2004-07-28 16:02:49Z joel $

// 1. define relative path to `include` directory:
define('AT_INCLUDE_PATH', '../include/');

// 2. require the `vitals` file before any others:
require (AT_INCLUDE_PATH . 'vitals.inc.php');

// 3. authenticate this user:
authenticate(AT_PRIV_SPECIAL_PRIV);

// 4. define the breadcrumbs path:
$_section[0][0] =  _AT('tools');
$_section[0][1] = 'tools/';
$_section[1][0] =  _AT('my_page');
$_section[1][1] =  'tools/page.php;

// 5. handle any post request:
if (isset($_POST['submit'])) {
  // 5.1 check for errors:
  if ($_POST['some_field'] == '') {
      $msg->addError('SOME_ERROR_CODE');
  }

  if (!$msg->containsErrors()) {
      //5.2 complete the desired action here. (example: insert into DB)

      //5.3 set the feedback message and add it to the URL:
      $msg->addFeedback('MESSAGE');
      $url = $_base_href . 'tools/index.php?arg1=yes';

      //5.4 redirect after successful operation:
      header('Location: ' . $url);
      exit;
  }
}

// 6. start the page display by calling the header
require (AT_INCLUDE_PATH . 'header.inc.php');

// 7. display any feedback or error messages that my occur:
require (AT_INCLUDE_PATH . 'html/feedback.inc.php');

/*
 * 8. display the page contents here.
 */

// 9. finish the page by calling the footer
require (AT_INCLUDE_PATH . 'footer.inc.php');
?>

top

24. Credits & Additional Sources