Defaults

Editor Settings

Tabs and Spaces

In order to simplify things, we use tabs, not spaces. When saving, make sure that when your editor saves the file, it's saving tabs and not spaces. This displays our source nicely without breaking any source layouts.

Check your editor's indent size! If tabs are set to 4 spaces, for example, the indent size needs to be 4 as well:

 $var{TAB}{TAB}= request_var('mode',NULL);
 $varvar_id{TAB}= request_var('search_id',NULL);

If entered with tabs (replace the {TAB}) both equal signs will be on the same column. This does not need to be applied to single, lone variables.

Linefeeds

Your editor should be saving files in the UNIX format meaning lines are terminated with a newline, not with a CR/LF combination. Most modern editors can do this.

File Header

Standard header for new files

This header template must be included at the start of all vMail.Admin files:

 /** 
 *
 * @package vMail.Admin 2
 * @version $Id: {FILENAME},v 1.0 2006/02/12 19:20:59 {YOUR_NAME} Exp $
 * @copyright (c) 2005 Erie Studio
 *
 **/
 
 /**
 *
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 **/

Commenting code

Multiple lines of comments

 /**
 *
 * {DOCUMENTATION}
 * {DOCUMENTATION}
 * {DOCUMENTATION}
 *
 **/


 {CODE}

Single line comment

 /* {DOCUMENTATION} */
 {CODE}

Files containing only functions

Document all functions. Each function must have at least one comment of what it does. For more complex comments and/or classes, please document the parameters too.For those files you have to put an empty comment directly after the header to prevent the documentor assigning the header to the first code element found.

Functions used by more than one page should be placed in functions.php, functions specific to one page should be placed on that page (at the bottom) or within the relevant functions file.

Files containing only classes

Document all classes. Each class must have at least one comment of what it does. Classes need a seperate @package definition:

 /** 
 *
 * {HEADER}
 *
 **/
 
 /**
 * 
 * @class {CLASSNAME}
 *         {DOCUMENTATON}
 *
 **/

Code Layout/Guidelines

Variable/Function Naming

Please note that these Guidelines also applies to Javascript.

Only English is to be used for our naming conventions. No exceptions!

Variable Names

Variable names should be in all lowercase, with words separated by an underscore, example:

 // Correct
 $this_domaindata
 // Incorrect
 $thisdomaindata
 $thisDomaindata

Names should be short but descriptive.

Loop Indices

The only situation where a one-character variable name is allowed is when it's the index for some looping construct. In this case, the index of the outer loop should always be $i. If there's a loop inside that loop, its index should be $j, followed by $k, and so on. If the loop is being indexed by some already-existing variable with a meaningful name, this guideline does not apply, example:

 for ($i = 0; $i < $outer_size; $i++)
 {
      for ($j = 0; $j < $inner_size; $j++)
      {
           foo($i, $j);
      }
 }

Function Names

Functions should also be named descriptively. We're not programming in C here, we don't want to write functions called things like "stristr()". Again, all lower-case names with words separated by a single underscore character. Function names should preferably have a verb in them somewhere. Good function names are print_login_status(), get_domain_data(), etc.

Function Arguments

Arguments are subject to the same guidelines as variable names. We don't want a bunch of functions like: do_stuff($a,$b,$c). In most cases, we'd like to be able to tell how to use a function by just looking at its declaration.

Summary

The basic philosophy here is to not hurt code clarity for the sake of laziness. A balance of common sense must exist, though; print_login_status_for_a_given_user() goes too far, for example -- that function would be better named print_user_login_status(), or just print_login_status().

Code Layout

All URL's must be passed to the tokenize() function. This function handles URI based sessions when cookies are not available therefore it is very important to take this extra step. In addition to handling sessions, the function also provides replacing special chars in URLs when needed..

 //For regular URLs
 tokenize($url)
 
 //For URLs for Header redirects and message_die()
 redirect(tokenize($url,TRUE))

Include braces for all if/then statments

 // Correct
 if (condition)
 {
     do_stuff();
 }
 
 while (condition) 
 {
     do_stuff();
 }
 
 for ($i = 0; $i < size; $i++) 
 {
     do_stuff();
 }
 // Correct
 if ( condition )
 {
     do_stuff();
 }
 
 while ( condition )
 {
     do_stuff();
 }

 for ($i = 0; $i < size; $i++) {do_stuff($i);}

Use spaces between tokens

This is another simple, easy step that helps keep code readable without much effort. Whenever you write an assignment, expression, etc.. Always leave one space between the tokens. Basically, write code as if it was English. Put spaces between variable names and operators. Don't put spaces just after an opening bracket or before a closing bracket. Don't put spaces just before a comma or a semicolon. This is best shown with a few examples, examples:

// Each pair shows the incorrect format followed by the correct format:
 $i=0;
 $i = 0;
 
 if($i<7) ...
 if ( $i < 7 ) ...
 
 if ( ($i < 7)&&($j > 8) ) ...
 if ( $i < 7 && $j > 8 ) ...
 
 do_stuff( $i, "foo", $b );
 do_stuff ($i,"foo",$b);
 
 for($i=0; $i<$size; $i++) ...
 for ( $i = 0; $i < $size; $i++ ) ... 
 
 $i=($j < $size)?0:1;
 $i = $j < $size ? 0 : 1;

Operator precedence

Do you know the exact precedence of all the operators in PHP? I most certainly do not. Never guess. Always make it obvious by using brackets to force the precedence of an equation so it performs the logic you want it to perform. However, do not not over-use this, as it may harden the readability. In short, do not enclose single expressions. Examples:

 // what's the result? who knows.
 $bool = ($i < 7 && $j > 8 || $k == 4);
 
 // now you can be certain what I'm doing here.
 $bool = (($i < 7) && (($j < 8) || ($k == 4)));
 
 // But this one is even better, because it is easier on the eye but the intention is preserved
 $bool = ($i < 7 && ($j < 8 || $k == 4));

Quoting strings

There are two different ways to quote strings in PHP - either with single quotes or with double quotes. The main difference is that the parser does variable interpolation in double-quoted strings, but not in single quoted strings. Because of this, you should always use single quotes unless you specifically need variable interpolation to be done on that string. This way, we can save the parser the trouble of parsing a bunch of strings where no interpolation needs to be done.

Also, if you are using a string variable as part of a function call, you do not need to enclose that variable in quotes. Again, this will just make unnecessary work for the parser. Note, however, that nearly all of the escape sequences that exist for double-quoted strings will not work with single-quoted strings. Be careful, and feel free to break this guideline if it's making your code easier to read, examples:

 // Correct
 $str = 'This is a really long string with no variables for the parser to find.';
 do_stuff($str);
 // Incorrect
 $str = "This is a really long string with no variables for the parser to find.";
 do_stuff("$str");

In SQL Statements mixing single and double quotes is partly allowed (following the guidelines listed here about SQL Formatting), else it should be tryed to only use one method - mostly single quotes.

Associative array keys

In PHP, it's legal to use a literal string as a key to an associative array without quoting that string. We don't want to do this -- the string should always be quoted to avoid confusion. Note that this is only when we're using a literal, not when we're using a variable, examples:

 // Correct
 $foo = $assoc_array['blah'];
 $foo = $assoc_array[$blah];
 // Incorrect
 $foo = $assoc_array[blah];
 $foo = $assoc_array['$blah'];

Using sprintf

We do not like to concat varibles. Instead, we use sprintf. Use this for ALL SQL statements to prevent SQL injections.

 // Use sprintf when variables are part of the declaration
 $page = sprintf('%s&domain_id=%d',$base,$domain_id);
 $sql = sprintf('SELECT * FROM %s',CONFIG_TABLE);

Comments

Each complex function should be preceded by a comment that tells a programmer everything they need to know to use that function. The meaning of every parameter, the expected input, and the output are required as a minimal comment. The function's behaviour in error conditions (and what those error conditions are) should also be present.

Especially important to document are any assumptions the code makes, or preconditions for its proper operation. Any one of the developers should be able to look at any part of the application and figure out what's going on in a reasonable amount of time. Avoid using /* */ comment blocks for one-line comments, /* */ should be used for one/two-liners, for example:

 /* One line comment */

Magic numbers

Don't use them. Use named constants for any literal value other than obvious special cases. Basically, it's ok to check if an array has 0 elements by using the literal 0. It's not ok to assign some special meaning to a number and then use it everywhere as a literal. This hurts readability AND maintainability. The constants true and false should be used in place of the literals 1 and 0 -- even though they have the same values (but not type!), it's more obvious what the actual logic is when you use the named constants. Typecast variables where it is needed, do not rely on the correct variable type (PHP is currently very loose on typecasting which can lead to security problems if a developer does not have a very close eye to it). Shortcut operators:

The only shortcut operators that cause readability problems are the shortcut increment $i++ and decrement $j-- operators. These operators should not be used as part of an expression. They can, however, be used on their own line. Using them in expressions is just not worth the headaches when debugging, examples:

 // Correct
 $i++;
 $array[$i] = $j;
 
 $array[$i] = $k;
 $i++;
 // Incorrect
 $array[++$i] = $j;
 $array[$i++] = $k;

Inline conditionals

Inline conditionals should only be used to do very simple things. Preferably, they will only be used to do assignments, and not for function calls or anything complex at all. They can be harmful to readability if used incorrectly, so don't fall in love with saving typing by using them, examples:

 // Bad place to use them
 $i < $size && $j > $size ? do_stuff($foo) : do_stuff($bar);
 // OK place to use them
 $min = $i < $j ? $i : $j;

Don't use uninitialized variables

Use of a higher level of run-time error reporting means that the use of an uninitialized variable will be reported as a warning. These warnings can be avoided by using the built-in isset() function to check whether a variable has been set, examples:

 // Correct
 if ( isset($var) ) ...
 if ( isset($var) && $var == 5 )
 // Incorrect
 if ($var) ...

Switch statements

Switch/case code blocks can get a bit long sometimes. To have some level of notice and being in-line with the opening/closing brace requirement (where they are on the same line for better readability), this also applies to switch/case code blocks and the breaks. An example:

 // Correct
 switch ($mode)
 {
      case 'mode1':
           foo();
           break;
 
      case 'mode2':
           foo2();
           break;
 
      default:
           foo3(); // Always assume case won't be matched
           break;
 }
 // Incorrect
 switch ($mode)
 {
      case 'mode1':
           // I am doing something here
      break;
 
      case 'mode2':
           // I am doing something completely different here
      break;
    }

Even if the break for the default case is not needed, it is sometimes better to include it just for readability and completeness.

If no break is intended, please add a comment instead. An example: the breaks. An example:

 // Correct
 switch ($mode)
 {
      case 'mode1':
           foo();
           // no break here
 
      case 'mode2':
           foo2();
           break;
 
      default:
           foo3(); // Always assume case won't be matched
           break;
 }

SQL/SQL Layout

SQL code layout

SQL Statements are often unreadable without some formatting, since they tend to be big at times. Though the formatting of sql statements adds a lot to the readability of code. SQL statements must be formatted and encapsulated in the sprintf function as follows:

 $sql = sprintf("SELECT *
 <-5 tabs-><-one space->FROM %s
 <-5 tabs-><-one space->WHERE a = 1 
 <-5 tabs-><-one space->AND (b = 2 
 <-5 tabs-><-one space->OR b = 3) 
 <-5 tabs-><-one space->ORDER BY b",
 <-5 tabs-><-one space->SOME_TABLE);

Here is the example with the tabs applied:

 $sql = sprintf("SELECT *
 		FROM %s
 		WHERE a = '1'
 		AND (b = '2'
 		OR b = '3')
 		ORDER BY b",
 		SOME_TABLE);

Styles

To create a new style, simply copy the default style to use as a template.

 cd /path/to/VMA/styles
 cp -f default NEW_STYLE_NAME

==Templating == All sytle templates must be saved as *.html files.

Change Log