This document provides the coding standards and guidelines for developers and teams working on or with the XOOPS Project. The subjects covered are:
Good coding standards are important in any development project, particularly when multiple developers are working on the same project. Having coding standards helps to ensure that the code is of high quality, has fewer bugs, and is easily maintained.
Abstract goals we strive for:
When considering the goals above, each situation requires an examination of the circumstances and balancing of various trade-offs.
For files that contain PHP code, the closing tag
("?>")
must be included where
necessary.
Use an indent of 4 spaces with no tab characters. Editors should be configured to treat tabs as four spaces in order to prevent injection of tab characters into the source code.
The target line length is 80 characters; i.e., developers should aim keep code as close to the 80-column boundary as is practical. However, longer lines are acceptable. The maximum length of any line of PHP code is 120 characters.
Line termination is the standard way for Unix text files. Lines must end only with a linefeed (LF). Linefeeds are represented as ordinal 10, or hexadecimal 0x0A.
Do not use carriage returns (CR) like Macintosh computers (0x0D).
Do not use the carriage return/linefeed combination (CRLF) as Windows computers (0x0D, 0x0A).
Lines should not contain trailing spaces. In order to facilitate this convention, most editors can be configured to strip trailing spaces, such as upon a save operation.
When creating an API for use by application developers, if application developers must identify abstractions using a compound name, separate the names using underscores, not camelCaps. When the developer uses a string, normalize it to lowercase. Where reasonable, add constants to support this.
Interface classes must follow the same conventions as other classes (see above), but must end with "_Interface", such as: XoopsLogger_Interface
For all files, only alphanumeric characters, underscores, and the dash character ("-") are permitted. Spaces are prohibited.
Any file that contains any PHP code must end
with the extension ".php".
For all directories, only alphanumeric characters, underscores, and the dash character ("-") are permitted. Spaces are prohibited.
Directory names must be in lowercase.Core, system module function names should start with xoops_doSomething([...]).
Framework function names should start with xoops_[lowercase of identifier]_, like xoops_pear_doSomething([...]).
Module function names should start with [lowercase of module identifier]_, like newbb_getTopic([...]).
Use "NULL" as the default value instead of "FALSE", for situations like this:
public function foo($required, $optional = NULL)
when $optional does not have or need a particular default value.
However, if an optional parameter is boolean, and its logical default value should be true, or false, then using true or false is acceptable.
System constants start with XOOPS_: XOOPS_URL
Framework constants should start with
XOOPS_[identifier]_:
XOOPS_PEAR_CONSTANT
Module constants should start with
[module
identifier]_:
NEWBB_CONSTANT
Always start with underscore:
_XOOPS_LANGUAGE_CONSTANT,
_NEWBB_LANGUAGE_CONSTANT
Like PHP's documentation, XOOPS uses uppercase
for both boolean values and the
"NULL"
value.
PHP code inside XOOPS must always be delimited
by the full-form, standard PHP tags:
<?php
?>
Short tags are never allowed.
Both "double quotes" and apostrophe or "single quote" are permitted for a string that is literal (contains no variable substitutions), "single quote" is encouraged:
$a = 'Example String';
When a literal string itself contains apostrophes, it is permitted to demarcate the string with quotation marks or "double quotes". This is especially encouraged for SQL statements:
$sql = "SELECT `id`, `name` from `people` WHERE `name`='Fred' OR `name`='Susan'";
The above syntax is preferred over escaping apostrophes.
Variable substitution is encouraged using brace.
$greeting = "Hello {$name}, welcome back!";
$greeting = "Hello $name, welcome back!";
For consistency, this form is not permitted:
$greeting = "Hello ${name}, welcome back!";
Strings may be concatenated using the "." operator. A space must always be added before and after the "." operator to improve readability:
$project = 'Xoops' . ' ' . 'Project';
When concatenating strings with the "." operator, it is permitted to break the statement into multiple lines to improve readability. In these cases, each successive line should be padded with whitespace such that the "." operator is aligned under the "=" operator:
$sql = "SELECT `id`, `name` FROM `people` "
. "WHERE `name` = 'Susan' "
. "ORDER BY `name` ASC ";
Negative numbers are not permitted as array indices.
An indexed array may be started with any non-negative number, however this is discouraged and it is recommended that all arrays have a base index of 0.
When declaring indexed arrays with the array construct, a trailing space must be added after each comma delimiter to improve readability:
$sampleArray = array(1, 2, 3, 'XOOPS', 'Project');
It is also permitted to declare multi-line indexed arrays using the array construct. In this case, each successive line must be padded with spaces such that beginning of each line aligns as shown below:
$sampleArray = array(1, 2, 3, 'XOOPS', 'Project',
$a, $b, $c,
56.44, $d, 500);
When declaring associative arrays with the array construct, it is encouraged to break the statement into multiple lines. In this case, each successive line must be padded with whitespace such that both the keys and the values are aligned:
$sampleArray = array('firstKey' => 'firstValue',
'secondKey' => 'secondValue');
Classes must be named by following the naming conventions.
The brace is always written on the line underneath the class name ("one true brace" form).
Every class must have a documentation block that conforms to the phpDocumentor standard.
Any code within a class must be indented the standard indent of four spaces.
It is encouraged to have only one class per PHP file.
Placing additional code in a class file is permitted but discouraged. In these files, two blank lines must separate the class from any additional PHP code in the file.
This is an example of an acceptable class declaration:
/**
* Class Docblock Here
*/
class XoopsClass
{
// entire content of class
// must be indented four spaces
}
Member variables must be named by following the variable naming conventions.
Any variables declared in a class must be listed at the top of the class, prior to declaring any functions.
The var construct is not permitted. Member variables always declare their visibility by using one of the private, protected, or public constructs. Accessing member variables directly by making them public is permitted, in certain cases it is in favor of accessor methods having the set get prefixes. and
Functions and class methods must be named by following the naming conventions.
Methods must always declare their visibility by using one of the private, protected, or public constructs.
Following the more common usage in the PHP developer community, static methods should declare their visibility first:
public static foo() { ... }
private static bar() { ... }
protected static goo() { ... }
As for classes, the opening brace for a function or method is always written on the line underneath the function or method name ("one true brace" form). There is no space between the function or method name and the opening parenthesis for the arguments.
This is an example of acceptable class method declarations:
/**
* Class Docblock Here
*/
class XoopsFoo
{
/**
* Method Docblock Here
*/
public function sampleMethod($a)
{
// entire content of function
// must be indented four spaces
}
/**
* Method Docblock Here
*/
protected function _anotherMethod()
{
// ...
}
}
The return value must not be enclosed in parentheses. This can hinder readability and can also break code if a function or method is later changed to return by reference.
function foo()
{
// WRONG
return($this->bar);
// RIGHT
return $this->bar;
}
The use of type hinting is encouraged where possible with respect to the component design. For example,
class XoopsComponent
{
public function foo(SomeInterface $object)
{}
public function bar(array $options)
{}
}
Functions in the global scope are strongly discouraged.
Function arguments are separated by a single trailing space after the comma delimiter. This is an example of an acceptable function call for a function that takes three arguments:
threeArguments(1, 2, 3);
Call-time pass by-reference is prohibited. Pass-by-reference is permitted in the function declaration only. Arguments to be passed by reference must be defined in the function declaration.
For functions whose arguments permit arrays, the function call may include the "array" construct and can be split into multiple lines to improve readability. In these cases, the standards for writing arrays still apply:
threeArguments(array(1, 2, 3), 2, 3);
threeArguments(array(1, 2, 3, 'XOOPS', 'Project',
$a, $b, $c,
56.44, $d, 500), 2, 3);
Control statements based on the "if", "else", and "elseif" constructs must have a single space before the opening parenthesis of the conditional, and a single space between the closing parenthesis and opening brace.
Within the conditional statements between the parentheses, operators must be separated by spaces for readability. Inner parentheses are encouraged to improve logical grouping of larger conditionals.
The opening brace is written on the same line as the conditional statement. The closing brace is always written on its own line. Any content within the braces must be indented four spaces.
if ($a != 2) {
$a = 2;
}
For "if" statements that include "elseif" or "else", the formatting must be as in these examples:
if ($a != 2) {
$a = 2;
} else {
$a = 7;
}
if ($a != 2) {
$a = 2;
} elseif ($a == 3) {
$a = 4;
} else {
$a = 7;
}
PHP allows for these statements to be written without braces in some circumstances. The coding standard makes no differentiation and all "if", "elseif", or "else" statements must use braces.
Control statements written with the "switch" construct must have a single space before the opening parenthesis of the conditional statement, and also a single space between the closing parenthesis and the opening brace.
All "case" items within the "switch" statement must not be indented. Content under each "case" statement must be indented an four spaces.
switch ($numPeople) {
case 1:
break;
case 2:
break;
default:
break;
}
The construct "default" may never be omitted from a "switch" statement.
All documentation blocks ("docblocks") must be compatible with the phpDocumentor format. For more information, visit http://phpdoc.org.
All source code file written for the XOOPS
platform or that operates with the platform must contain a "file-level"
docblock at the top of each file and a "class-level" docblock immediately
above each class.
The sharp, '#', character should not be used to start comments.w
Every file that contains PHP code must have a header block at the top of the file that contains these phpDocumentor tags at a minimum:
/**
* Short description for file
*
* Long description for file (if any)...
*
* LICENSE
*
* You may not change or alter any portion of this comment or credits* of supporting developers from this source code or any supporting source code
* which is considered copyrighted (c) material of the original comment or credit authors.
*
* @copyright The XOOPS Project http://sourceforge.net/projects/xoops/* @license http://www.fsf.org/copyleft/gpl.html GNU public license
* @author Author Name <author email, or website>
* @version $Id$
* @since File available since Release 3.0.0
*/
Every class must have a docblock that contains these phpDocumentor tags at a minimum:
/**
* Short description for class
*
* Long description for class (if any)...
*
* @copyright The XOOPS Project http://sourceforge.net/projects/xoops/
* @license http://www.fsf.org/copyleft/gpl.html GNU public license
* @author Author Name <author email, or website>
* @version $Id$
* @since File available since Release 3.0.0
*/
Every function, including object methods, must have a docblock that contains at a minimum:
/**
* Does something interesting
*
* @param Place $where Where something interesting takes place
* @param integer $repeat How many times something interesting should happen
* @return Status
*/
public function xoops_doSomethingInteresting(Place $where, $repeat = 1)
{
// implementation...
}
If a component uses another component, then the using component is responsible for loading the other component. If the use is conditional, then the loading should also be conditional.
If the file(s) for the other component should
always load successfully, regardless of input, then use PHP's
require_once statement.
Use XoopsLoad::load() to load
configured classes.
The
include,
include_once,
require, and
require_once statements should
not use parentheses.
The XOOPS Project codebase must be E_STRICT compliant. XOOPS code should not emit PHP warning (E_WARNING, E_USER_WARNING), notice (E_NOTICE, E_USER_NOTICE), or strict (E_STRICT) messages when error_reporting is set to E_ALL | E_STRICT.
See http://www.php.net/errorfunc for information on E_STRICT.
XOOPS code should not emit PHP errors, if it is reasonably possible. Instead, log each error with meaningful messages using trigger_error function then XOOPS will use custom error handler for subsequent processing.