DONATE:2012 Spring Object Design Document

=Coding standards=

Indenting and Whitespace
All text files should end in a single newline (\n). This avoids the verbose "\ No newline at end of file" patch warning and makes patches easier to read since it's clearer what is being changed when lines are added to the end of a file.
 * Use an indent of 2 spaces, with no tabs.
 * Lines should have no trailing whitespace at the end.
 * Files should be formatted with \n as the line ending (Unix line endings), not \r\n (Windows line endings).

Operators
All binary operators (operators that come between two values), such as +, -, =, !=, ==, >, etc. should have a space before and after the operator, for readability. For example, an assignment should be formatted as $foo = $bar; rather than $foo=$bar;. Unary operators (operators that operate on only one value), such as ++, should not have a space between the operator and the variable or number they are operating on.

Casting
Put a space between the (type) and the $variable in a cast: (int) $mynumber.

Control Structures
Control structures include if, for, while, switch, etc. Here is a sample if statement, since it is the most complicated of them: if (condition1 || condition2) { action1; } elseif (condition3 && condition4) { action2; } else { defaultaction; } Control statements should have one space between the control keyword and opening parenthesis, to distinguish them from function calls. Always use curly braces even in situations where they are technically optional. Having them increases readability and decreases the likelihood of logic errors being introduced when new lines are added. For switch statements: switch (condition) { case 1: action1; break; case 2: action2; break; default: defaultaction; } For do-while statements: do { actions; } while ($condition);

Alternate control statement syntax for templates
In templates, the alternate control statement syntax using : instead of brackets is allowed. Note that there should not be a space between the closing paren after the control keyword, and the colon, and HTML/PHP inside the control structure should be indented. For example:   

  

Line length and wrapping
The following rules apply to code. See Doxygen and Documentation for more rules on commenting. if ($something['with']['something']['else']['in']['here'] == mymodule_check_something($whatever['else'])) { ... }  if (isset($something['what']['ever']) && $something['what']['ever'] > $infinite && user_access('galaxy')) { ... }  // Non-obvious conditions of low complexity are also acceptable, but should // always be documented, explaining WHY a particular check is done. if (preg_match('@(/|\\)(\.\.|~)@', $target) && strpos($target_dir, $repository) !== 0) { return FALSE; } // DON'T DO THIS! if ((isset($key) && !empty($user->uid) && $key == $user->uid) || (isset($user->cache) ? $user->cache : '') == ip_address || isset($value) && $value >= time)) {   ...  }
 * In general, all lines of code should not be longer than 80 chars.
 * Lines containing longer function names, function/class definitions, variable declarations, etc are allowed to exceed 80 chars.
 * Control structure conditions may exceed 80 chars, if they are simple to read and understand:
 * Conditions should not be wrapped into multiple lines.
 * Control structure conditions should also NOT attempt to win the Most Compact Condition In Least Lines Of Code Award™:

Instead, it is recommended practice to split out and prepare the conditions separately, which also permits documenting the underlying reasons for the conditions: // Key is only valid if it matches the current user's ID, as otherwise other // users could access any user's things. $is_valid_user = (isset($key) && !empty($user->uid) && $key == $user->uid);

// IP must match the cache to prevent session spoofing. $is_valid_cache = (isset($user->cache) ? $user->cache == ip_address : FALSE);

// Alternatively, if the request query parameter is in the future, then it // is always valid, because the galaxy will implode and collapse anyway. $is_valid_query = $is_valid_cache || (isset($value) && $value >= time);

if ($is_valid_user || $is_valid_query) { ... }

Function Calls
Functions should be called with no spaces between the function name, the opening parenthesis, and the first parameter; spaces between commas and each parameter, and no space between the last parameter, the closing parenthesis, and the semicolon. Here's an example: $var = foo($bar, $baz, $quux); As displayed above, there should be one space on either side of an equals sign used to assign the return value of a function to a variable. In the case of a block of related assignments, more space may be inserted to promote readability: $short        = foo($bar); $long_variable = foo($baz);

Function Declarations
function funstuff_system($field) { $system["description"] = t("This module inserts funny text into posts randomly."); return $system[$field]; } Arguments with default values go at the end of the argument list. Always attempt to return a meaningful value from a function if one is appropriate.

Class Constructor Calls
When calling class constructors with no arguments, always include parentheses: $foo = new MyClassName;

This is to maintain consistency with constructors that have arguments: $foo = new MyClassName($arg1, $arg2);

Note that if the class name is a variable, the variable will be evaluated first to get the class name, and then the constructor will be called. Use the same syntax: $bar = 'MyClassName'; $foo = new $bar; $foo = new $bar($arg1, $arg2);

Arrays
Arrays should be formatted with a space separating each element (after the comma), and spaces around the => key association operator, if applicable: $some_array = array('hello', 'world', 'foo' => 'bar'); Note that if the line declaring an array spans longer than 80 characters (often the case with form and menu declarations), each element should be broken into its own line, and indented one level: $form['title'] = array(   '#type' => 'textfield',    '#title' => t('Title'),    '#size' => 60,    '#maxlength' => 128,    '#description' => t('The title of your node.'),  ); ''Note the comma at the end of the last array element; This is not a typo! It helps prevent parsing errors if another element is placed at the end of the list later.''

Quotes
Drupal does not have a hard standard for the use of single quotes vs. double quotes. Where possible, keep consistency within each module, and respect the personal style of other developers. With that caveat in mind: single quote strings are known to be faster because the parser doesn't have to look for in-line variables. Their use is recommended except in two cases: 1.	In-line variable usage, e.g. "$header". 2.	Translated strings where one can avoid escaping single quotes by enclosing the string in double quotes. One such string would be "He's a good person." It would be 'He\'s a good person.' with single quotes. Such escaping may not be handled properly by .pot file generators for text translation, and it's also somewhat awkward to read.

String Concatenations
Always use a space between the dot and the concatenated parts to improve readability.  When you concatenate simple variables, you can use double quotes and add the variable inside; otherwise, use single quotes.  When using the concatenating assignment operator ('.='), use a space on each side as with the assignment operator: 

Functions and variables
Functions and variables should be named using lowercase, and words should be separated with an underscore. Functions should in addition have the grouping/module name as a prefix, to avoid name collisions between modules.

Persistent Variables
Persistent variables (variables/settings defined using Drupal's variable_get/variable_set functions) should be named using all lowercase letters, and words should be separated with an underscore. They should use the grouping/module name as a prefix, to avoid name collisions between modules.

Constants
 Note that const does not work with PHP expressions. define should be used when defining a constant conditionally or with a non-literal value: 
 * Constants should always be all-uppercase, with underscores to separate words. (This includes pre-defined PHP constants like TRUE, FALSE, and NULL.)
 * Module-defined constant names should also be prefixed by an uppercase spelling of the module that defines them.

Global Variables
If you need to define global variables, their name should start with a single underscore followed by the module/theme name and another underscore.

Classes
Classes should be named using "CamelCase." For example:  Class methods and properties should use "lowerCamelCase":  The use of private class methods and properties should be avoided -- use protected instead, so that another class could extend your class and change the method if necessary. Protected (and public) methods and properties should not use an underscore prefix, as was common in PHP 4-era code.

File names
All documentation files should have the file name extension ".txt" to make viewing them on Windows systems easier. Also, the file names for such files should be all-caps (e.g. README.txt instead of readme.txt) while the extension itself is all-lowercase (i.e. txt instead of TXT). Examples: README.txt, INSTALL.txt, TODO.txt, CHANGELOG.txt etc

=General documentation standards= These standards apply to both in-line and header comments:
 * All documentation and comments should form proper sentences and use proper grammar and punctuation.
 * Sentences should be separated by single spaces.
 * Comments and variable names should be in English, and use US English spelling (e.g., "color" not "colour").
 * All caps are used in comments only when referencing constants, for example TRUE
 * Comments should be word-wrapped if the line length would exceed 80 characters (i.e., go past the 80th column, including any leading spaces and comment characters in the 80 character count). They should be as long as possible within the 80-character limit.

In-line comment standards
Non-header or in-line comments are strongly encouraged. A general rule of thumb is that if you look at a section of code and think "Wow, I don't want to try and describe that", you need to comment it before you forget how it works. Comments should be on a separate line immediately before the code line or block they reference. For example: // Unselect all other contact categories. db_query('UPDATE {contact} SET selected = 0'); If each line of a list needs a separate comment, the comments may be given on the same line and may be formatted to a uniform indent for readability.

General header documentation syntax
To document a block of code, such as a file, function, class, method, constant, etc., the syntax we use is: /** * Documentation here. */ Doxygen will parse any comments located in such a block. Our style is to use as few Doxygen-specific commands as possible, so as to keep the source legible. Any mentions of functions, classes, file names, topics, etc. within the documentation will automatically link to the referenced code, so typically no markup need be introduced to produce links. The documentation block should appear immediately before the function, class, method, etc. that is being documented, with no blank lines in between.

Doxygen directives - general notes
/** * Summary here; one sentence on one line (should not, but can exceed 80 chars). * * A more detailed description goes here. * * A blank line forms a paragraph. There should be no trailing white-space * anywhere. * * @param $first *  "@param" is a Doxygen directive to describe a function parameter. Like some *  other directives, it takes a term/summary on the same line and a  *   description (this text) indented by 2 spaces on the next line. All *  descriptive text should wrap at 80 chars, without going over. *  Newlines are NOT supported within directives; if a newline would be before *  this text, it would be appended to the general description above. * @param $second *  There should be no newline between multiple directives (of the same type). * @param $third *  (optional) TRUE if Third should be done. Defaults to FALSE. *  Only optional parameters are explicitly stated as such. The description *  should clarify the default value if omitted. * * @return *  "@return" is a different Doxygen directive to describe the return value of  *   a function, if there is any. */ function mymodule_foo($first, $second, $third = FALSE) { }

Lists
* @param $variables *  An associative array containing: *  - tags: An array of labels for the controls in the pager: *    - first: A string to use for the first pager element. *    - last: A string to use for the last pager element. *  - element: (optional) Integer to distinguish between multiple pagers on one *    page. Defaults to 0 (zero). *  - style: Integer for the style, one of the following constants: *    - PAGER_FULL: (default) Full pager. *    - PAGER_MINI: Mini pager. *  Any further description - still belonging to the same param, but not part *  of the list. * * This no longer belongs to the param. Lists can appear anywhere in Doxygen. The documentation parser requires you to follow a strict syntax to make them appear correctly in the parsed HTML output:
 * A hyphen is used to indicate the list bullet. The hyphen is aligned with (uses the same indentation level as) the paragraph before it, with no newline before or after the list.
 * No newlines between list items in the same list.
 * Each list item starts with the key, followed by a colon, followed by a space, followed by the key description. The key description starts with a capital letter and ends with a period.
 * If the list has no keys, start each list item with a capital letter and end with a period.
 * The keys should not be put in quotes unless they contain colons (which is unlikely).
 * If a list element is optional or default, indicate (optional) or (default) after the colon and before the key description.
 * If a list item exceeds 80 chars, it needs to wrap, and the following lines need to be aligned with the key (indented by 2 more spaces).
 * For text after the list that needs to be in the same block, use the same alignment/indentation as the initial text.
 * Again: within a Doxygen directive, or within a list, blank lines are NOT supported.
 * Lists can appear within lists, and the same rules apply recursively.

Documenting files
Each file should start with a comment describing what the file does. For example: /** * @file * The theme system, which controls the output of Drupal. * * The theme system allows for nearly all output of the Drupal system to be  * customized by user themes. */

Note that a blank line should follow a @file documentation block.

The line immediately following the @file directive is a summary that will be shown in the list of all files in the generated documentation. (Like other summaries, it should be one sentence in one line of up to 80 characters.) If the line begins with a verb, that verb should be in present tense, e.g., "Handles file uploads." Further description may follow after a blank PHPDoc line.

In general, @file directives should not contain large descriptions, because those are better placed into @defgroup directives, so developers can look up high-level documentation by reading the "group" topic. See http://api.drupal.org/api/drupal/groups for a list of API topics/groups in Drupal Core. For .install files, the following template is used: /** * @file * Install, update, and uninstall functions for the XXX module. */ For files containing the definition of exactly one class, use this template: /** * @file * Definition of NameOfTheClass. */

Documenting functions and methods
All functions and methods, whether meant to be private or public, should be documented. A function documentation block should immediately precede the declaration of the function itself. For example: /** * Verifies the syntax of the given e-mail address. * * Empty e-mail addresses are allowed. See RFC 2822 for details. * * @param $mail *  A string containing an email address. * * @return *  TRUE if the address is in a valid format, and FALSE if it isn't.  */ function valid_email_address($mail) { Note that some types of functions have special forms of documentation that do not follow this exact format -- see sections below for details (e.g., hook declarations, form generating functions, etc.).

Notes on function documentation syntax
First line: description

The first line of the block should contain a brief description of what the function does, limited to 80 characters, and beginning with a verb in the form "Does such and such" (third person, as in "This function does such and such", rather than second person imperative "Do such and such").

Additional description

A longer description with usage notes should follow after a blank line, if more explanation is needed.

Parameters

After the long description, each parameter should be listed with a @param directive, with a description indented by two extra spaces on the following line or lines. If there are no parameters, omit the @param section entirely. Do not include any blank lines in the @param section.

Variable arguments

If a function uses variable arguments, use this syntax: * @param ... *    Description of the variable arguments goes here.

Return value

After all the parameters, a @return directive should be used to document the return value if there is one. There should be a blank line between the @param section and @return directive. If there is no return value, omit the @return directive entirely.

Short form

Functions that are easily described in one line may use the function summary only, for example: /** * Converts an associative array to an anonymous object. */ function mymodule_array2object($array) { If the abbreviated syntax is used, the parameters and return value must be described within the one-line summary.

Data types on param/return

The data type of a parameter or return value MUST be specified in @param or @return directives, if it is not obvious or of a specific class or interface type. The data type MAY be specified (as in: recommended) for other @param or @return directives, including those with primitive data types, arrays, and generic objects (stdClass).
 * @param int $number: Description of this parameter, which takes an integer.
 * @param float $number: Description of this parameter, which takes a floating-point number.
 * @param string $description: Description of this parameter, which takes a string.
 * @param bool $flagged: Description of this parameter, which takes a Boolean TRUE/FALSE value.
 * @param array $args: Description of this parameter, which takes a PHP array value.
 * @param object $account: Description of this parameter, which takes a PHP stdClass value.
 * @param DatabaseStatementInterface $query: Description of this parameter, which takes an object of a class that implements the DatabaseStatementInterface interface.
 * @param string|bool $string_or_boolean: Description of this parameter, which takes a string or a Boolean TRUE/FALSE value.
 * @param string|null $string_or_null: (optional) Description of this optional parameter, which takes a string or can be NULL.
 * @return string: Description of the return value, which is a string.

Notes:
 * For primitive and non-specific types, use the lower-case type name; int, string, bool, array, object, etc.
 * For special constants, use the lower-case value name: null, false, true. Use bool instead of true|false though. Only specify true or false if the opposite is not supported (e.g., @return string|false).
 * For optional parameters, the default value should only be mentioned on the @param line if its type differs from non-default values. For instance, use @param string|null or @param int|false but never @param string|'' or @param int|0.
 * For classes and interfaces, use the most general class/interface possible. For example, the return value of db_select is properly documented as SelectQueryInterface rather than a particular class implementation such as SelectQuery.
 * Return values are documented by @return and use the same conventions as @param, but with no variable name.
 * If a function may return NULL in some but not all cases, then document this possibility. For instance, if the return value may either be a string value or NULL, then use @return string|null followed by a description of the circumstances in which each may be returned.
 * The @return section should be omitted if the function lacks an explicit return value.
 * In general, if there are more than two choices (e.g., string|bool|null) for a parameter or return data type, the function should probably be refactored for simplicity.

Documenting classes and interfaces
Each class and interface should have a doxygen documentation block, and each member variable, constant, and function/method within the class or interface should also have its own documentation block. Example: <?php /** * Defines a common interface for a prepared statement. */ interface DatabaseStatementInterface extends Traversable {

/**    * Executes a prepared statement. *    * @param array $args *  Array of values to substitute into the query. * @param array $options *  Array of options for this query. *    * @return *  TRUE on success, FALSE on failure. */   public function execute($args = array, $options = array); }

/**   * Represents a prepared statement. *   * Default implementation of DatabaseStatementInterface. */   class DatabaseStatementBase extends PDOStatement implements DatabaseStatementInterface {

/**    * The database connection object for this statement's DatabaseConnection. *    * @var DatabaseConnection */   public $dbh;

/**    * Constructs a DatabaseStatementBase object. *    * @param DatabaseConnection $dbh *  Database connection object. */   protected function __construct($dbh) { // Function body here. }

/**    * Implements DatabaseStatementInterface::execute. *    * Optional explanation of the specifics of this implementation goes here. */   public function execute($args = array, $options = array) { // Function body here. }

/**    * Returns the foo information. *    * @return object *  The foo information as an object. *    * @throws MyFooUndefinedException */   public function getFoo { // Function body here. }

/**    * Overrides PDOStatement::fetchAssoc. *    * Optional explanation of the specifics of this override goes here. */   public function fetchAssoc { // Call PDOStatement::fetch to fetch the row. return $this->fetch(PDO::FETCH_ASSOC); } }  ?> Notes:
 * Leave a blank line between class declaration and first internal docblock.
 * Make sure to have a docblock on each member variable and method. Short documentation forms should be used for the overridden/extended methods (don't repeat what is documented on the base method, just link to it by saying "Overrides BaseClassName::method." or "Implements BaseInterfaceName::method.", and then document any specifics to this implementation, leaving out param/return docs).
 * Use a 3rd person verb to begin the description of a class, interface, or method (e.g. Represents not Represent).
 * For a member variable, use @var to tell what data type the variable is.
 * Use @throws if your method can throw an exception, followed by the name of the exception class. If the exception class is not specific enough to explain why the exception will be thrown, you should probably define a new exception class.
 * Make sure when documenting function and method return values, as well as member variable types, to use the most general class/interface possible. E.g., document the return value of db_select to be a SelectQueryInterface, not a particular class that implements SelectQuery.

=Doxygen Documentation=

Keyword Substitutions
 * 1 Change the SVN Properties on each file as below

Set Author Date ID and Revision
 * 2 Add to each files comment section for example – we could put the repository URL in each as well

Last committed:    $Revision$ Last changed by:   $Author$ Last changed date:   $Date$ ID:                $Id$


 * 3 Once changed the next commit adds the relevant data to the comment header and will do from then on