Drupal Coding Standards

Evgeniy Melnikov
www.angarsky.ru
@angarsky
Why do coding standards need?
function pdf_taxonomy_term_page($tids, $result) {
$term = taxonomy_get_term($tids[0]);
//dpm($term);
//if(taxonomy_term_count_nodes($tids[0], 'media') < 1) {
if($term->vid==14) {
$o = '';
//$t = taxonomy_get_term($tids[0]);
$w = db_query('SELECT %s, %s FROM {term_fields_term} WHERE tid = %d', 'url', 'job_title', $tids[0]);
$record = db_fetch_object($w);
//dpm($record);
if(!empty($record->job_title)) {
$o .= '<h4 class="subtitle">'.$record->job_title.'</h4>';
}
$o .= '<div class="taxonomy_image_display">' . taxonomy_image_display($tids[0]) . '</div>'; // image
if (!empty($term->description))
{
$d = filter_xss_admin($term->description);
$o .= '<div class="taxonomy-term-description">'. $d .'</div>';
}
if(!empty($record->url)) {
$w1 = explode('/', $record->url); // explode an URL
$o .= '<div class="twitter">Twitter: <a href="http://' . $record->url . '" class="speaker-twitter">@'
. $w1[count($w1)-1] . '</a></div>';
}
return $o;
}
return theme_taxonomy_term_page($tids, $result);
}
Why do coding standards need?
- improve a code readability
- prevent occasional errors
- save a time for your team members
- help in debugging
Drupal Coding Standards
https://www.drupal.org/coding-standards
Indenting and Whitespace
- Use an indent of 2 spaces, with no tabs.
- Lines should have no trailing whitespace at the end.
- All text files should end in a single newline (\n).
/**
* Implements hook_menu().
*/
function node_menu() {
$items['admin/content'] = array(
'title' => 'Content',
'description' => 'Find and manage content.',
'page callback' => 'drupal_get_form',
'page arguments' => array('node_admin_content'),
'access arguments' => array('access content overview'),
'weight' => -10,
'file' => 'node.admin.inc',
);
return $items;
}
Operators
- All binary operators have a space before and after the operator, for readability.
- Unary operators should not have a space between the operator and the variable or number they are operating on.
function example_function() {
$a = 5;
$b = 6;
$items = 0;
// Binary operators.
if ($b > $a) {
$items = $a + $b;
}
// Unary operator.
$items++;
return $items;
}
Control Structures
"IF-ELSE"
function example_function($a, $b) {
if ($b > $a) {
$items = $a + $b;
}
elseif ($b == $a) {
$items = $a * 2;
}
else {
$items = FALSE;
}
return $items;
}
Control Structures
"SWITCH"
function example_function($a) {
switch ($a) {
case 1:
case 2:
$items = 0;
break;
case 3:
$items = 1;
break;
default:
$items = FALSE;
}
return $items;
}
Control Structures
"DO-WHILE"
function example_function($a) {
do {
$a++;
$items = $a;
} while ($a < 5);
return $items;
}
Control Structures
Alternate control statement syntax for templates
<?php if (!empty($item)): ?>
<p><?php print $item; ?></p>
<?php endif; ?>
<?php foreach ($items as $item): ?>
<p><?php print $item; ?></p>
<?php endforeach; ?>
Line length and wrapping
- In general, all lines of code should not be longer than 80 characters.
- Lines containing longer function names, function/class definitions, variable declarations, etc are allowed to exceed 80 characters.
- Control structure conditions may exceed 80 characters, if they are simple to read and understand
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;
}
}Line length and wrapping
- 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™
// DON'T DO THIS!
if ($key == $user->uid) || (isset($user->cache) ? $user->cache : '') == ip_address()) {
...
}
// GOOD EXAMPLE.
$user_cache = isset($user->cache) ? $user->cache : '');
if ($key == $user->uid) || $user_cache == ip_address()) {
...
}Function Declarations & Calls
- Functions should be declared with no spaces between the function name, the opening parenthesis, and the first parameter
- Arguments with default values go at the end of the argument list
- Don't forget to add a comment with description for your function
/**
* My function.
*
* @param $system
* @param $field
* @param string $extra
* @return mixed
*/
function example_function($system, $field, $extra = '') {
$system[$field] = $extra;
return $system;
}
Function Declarations & Calls
- Functions should be called with no spaces between the function name, the opening parenthesis, and the first parameter
- Add spaces between commas and each parameter
- Don't add spaces between the last parameter, the closing parenthesis, and the semicolon
$var = example_function($system, $field, $data);
// In the case of a block of related assignments,
// more space may be inserted to promote readability.
$short = foo($bar);
$long_variable = foo($baz);
Arrays
- Arrays should be formatted with a space separating each element (after the comma), and spaces around the => key association operator, if applicable
- 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
$some_array = array('hello', 'world', 'foo' => 'bar');
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#size' => 60,
'#maxlength' => 128,
'#description' => t('The title of your node.'),
);
String Concatenations
- Always use a space between the dot and the concatenated parts to improve readability
$string = 'Foo' . $bar;
$string = $bar . 'foo';
$string = bar() . 'foo';
$string = 'foo' . 'bar';
$string .= 'Foo';
$string .= $bar;
$string .= baz();- When you concatenate simple variables, you can use double quotes and add the variable inside; otherwise, use single quotes
$string = "Foo $bar";
Comments
Drupal standards for in-line code comments
// Comments should be on a separate line immediately before
// the code line or block they reference.
$string = 'Foo' . $bar;
// Some other comment here.
// @todo: Example of todo.
comment_delete($cid);Comments
Drupal API documentation standards for functions
-
Each parameter of a function must be documented with a @param tag
-
If a function has a return value, it must be documented with a @return tag
-
If there is no return value for a function, there must not be a @return tag
-
For most functions (see exceptions below), summary lines must start with a third person singular present tense verb, and they must explain what the function does. Example: "Calculates the maximum weight for a list."
-
Functions that are easily described in one line may be documented by providing the function summary line only (omitting all parameters and return value)
Comments
Drupal API documentation standards for functions
/**
* My function.
*
* Updates a System array for next functions.
*
* @param array $system
* My array with data.
* @param string $field
* Field name.
* @param string $extra
* String with translated text.
* @return array
* System array with updated info.
*/
function my_example_system($system, $field, $extra = '') {
$system[$field] = $extra;
return $system[$field];
}
Comments
Hook implementation
/**
* Implements hook_menu_alter().
*/
function my_module_menu_alter(&$items) {
// Example - disable the page at node/add.
$items['node/add']['access callback'] = FALSE;
}
There is no need to document parameters and returned value for hooks.
Comments
Form-generating functions
/**
* Form constructor for the user login form.
*
* @param string $message
* The message to display.
*
* @see user_login_form_validate()
* @see user_login_form_submit()
*
* @ingroup forms
*/
function user_login_form($form, &$form_state, $message = '') {
...
}
- Omit @param and @return documentation for the standard parameters and return value (such as $form and $form_state
- Document parameters specific to this form constructor
Comments
Themeable functions
/**
* Returns HTML for a foo.
*
* @param array $variables
* An associative array containing:
* - foo: The foo object that is being formatted.
* - show_bar: TRUE to show the bar component, FALSE to omit it.
*
* @ingroup themeable
*/
function theme_foo($variables) {
...
}
- The first line should be "Returns HTML for a ..."
- All components of the $variables array (or other arguments) need to be documented.
- They should have @ingroup themeable in their documentation.
Comments
Tag references
@deprecated: Indicating deprecated functionality
The @deprecated tag is placed in a documentation block to indicate that a function, method, or class has been deprecated and should not be used, but has not yet been removed.
@file: Documenting files
The @file tag is placed in a docblock to indicate it is documentation for the file as a whole. The API module will only recognize one file docblock per file (the first one; there shouldn't be more than one).
Comments
Tag references
@see: See Also references
The @see tag is used in a docblock to indicate a "See Also" reference. The API module collects these and formats them into a single See Also section on the documentation page.
@todo: To Do notes
The @todo tag is used to place To Do notes in documentation. At this time, the API module does not do anything special with these notes, so they are simply displayed as paragraphs of text with the @todo tag left in.
Comments
Write a code comments - it will save your time in future!
https://www.drupal.org/node/1354
PHP Code Tags
- Always use <?php ?> to delimit PHP code, not the shorthand, <? ?>.
- Don't use ?> in the end of code files (removing it eliminates the possibility for unwanted whitespace at the end of files which can cause "header already sent" errors, XHTML/XML validation issues, and other problems)
Naming Conventions
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.
Naming Conventions
Constants
- 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.

That's it about Drupal Coding Standards!

Helper modules

- Coder - http://drupal.org/project/coder
- Dreditor - http://drupal.org/project/dreditor
- PAReview - http://drupal.org/project/pareviewsh
- Code Sniffer - http://drupal.org/node/1419980
Let's find all mistakes
<?
/**
* Implements hook_theme().
*/
function barsam_theme(){
return array(
'ingredient_item' => array(
'variables' => array(
'amount' => '',
'measure' => '',
'ingredient' => '',
),
),
);
}
/**
* Theme of 'ingredient_item'.
*
* @param $variables
* @return string
*/
function theme_ingredient_item($variables){
$amountItem = $variables['amount'];
$output = '';
if ($amountItem > 10){
$output .= 'More than 10.';
} else {
$output = 'Amount is '.$amountItem;
}
return $output;
}Questions?

Drupal Coding Standards
Evgeniy Melnikov
www.angarsky.ru
@angarsky
DS - Coding standards
By Semen Angarsky
DS - Coding standards
- 271