Coding Standards

Nicolas Jeannerod edited this page Jun 15, 2016 · 8 revisions

Abstract

The purpose of this document is to establish a standard for all PHP and HTML code written for Ampache. This document will outline stylistic standards for code such as indentation and spacing. It will also detail naming conventions for functions and files as well as the logical layout of files under the web space. It will also outline some basic coding practices, or standards that all new Ampache PHP code should meet.

Automatic Coding Standards check

Ampache automatically check each commit in respect to this Coding Standards using Travis build. Please make sure your commits/pull requests doesn't break the build checking your files locally with php-cs-fixer utility.

  • Go to your local Ampache directory
  • Download php-cs-fixer (version 1)
  • Run php php-cs-fixer.phar fix -v --fixers=indentation,linefeed,trailing_spaces,short_tag,braces,controls_spaces,eof_ending,visibility,align_equals,concat_with_spaces,elseif,line_after_namespace,lowercase_constants,encoding .

Indentation and Line Length

Use an indent of a four spaces. It is recommended that you break lines at approximately 75-85 characters. There is no standard rule for the best way to break a line, please use your best judgment. The goal is to make the PHP files easy to read by a third party.

Control Structures

These include if, for, while, switch, etc. Here is an example if statement, since it can be the most complicated:

if

if ((condition1) || (condition2)) {
    action1;
}
elseif ((condition3) && (condition4)) {
    action2;
}
else {
    defaultaction;
}

if (condition1) {
    while ($foo) { 
        do_stuff();
    }
}

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.

switch (simple)

switch (condition) {
    case 1: action1; break;
    case 2: action2; break;
    default: defaultaction; break;
} 

switch (complex)

switch (condition) { 
    case 1: 
        action1;
        action2;
    break;
    case 2:
    case 3:
        action1;
        action2;
    break;
    default:
        action1;
    break;
} // end switch condition

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.

Function call 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, assignments can be aligned to promote readability:

$short         = foo($bar);
$long_variable = foo($baz);

Operators

Binary and ternary operators should be fully spaced out. Unary operators will generally not be.

$foo = $bar . 'baz';
$foo = $bar ? $baz : $quux;
$foo = !$baz;
$foo++;

Special Language Constructs

echo, require, and require_once are not functions and do not require parentheses around their arguments. To distinguish them from real function calls, do not use the optional parentheses when calling them.

require_once 'lib/init.php';
echo 'Initialised.';

Variable and Function Definitions

Classes

Classes should be given descriptive names. Avoid using abbreviations where possible. Class names should always begin with an uppercase letter. The class hierarchy is also reflected in the class name. Classes should be named using Camel_Caps. Examples of good class names are:

  • Log
  • Net_Finger
  • HTML_Upload_Error

Functions and Methods

Functions and methods should be named with all lower case using underscores between words or levels of hierarchy

  • connect();
  • get_data();
  • build_some_widget();
  • xmlrpc_serialize_data();
  • xmlrpc_unserialize_data();

Naming Conventions

Follow the below naming conventions when creating new functions to make your code easy to read. When creating functions use the following prefixes:

  • print //echo info//
  • get //get info//
  • show //include html//
  • create //create object//
  • delete //delete object//
  • update //update object//
  • clean //verify, data integrity checks/modification//
  • check //error checking//
  • has //check if object has property//
  • exec //run a process//
  • format //Re-formats existing data//
  • put //Inserting data into lists,database,files,objects etc//

Naming Examples

/* Echoes information, doesn't return */
print_foo() 
/* Returns information */
get_foo() 
/* Gets information then includes an html template */
show_foo() 
/* Create new Object */
create_foo() 
/* Delete Object */
delete_foo()

Private members

Private class members (meaning class members that are intended to be used only from within the same class in which they are declared; PHP does not yet support truly-enforceable private name spaces) should be preceded by a single underscore. For example:

  • _sort();
  • _init_tree();
  • $this->_status;

Constants

Constants should always be all-uppercase, with underscores to separate words. The true, false and null constants are excepted from the all-uppercase rule, and must always be lowercase.

Variable Names

In the interest of future readability, code should always use full named variables unless a commonly known acronym can be used in its place. For example

// An Upload Directory
$upload_directory   = '/tmp';
// XMLRPC result
$xmlrpc_result  = $xmlrpc->get_results();

Code Comments

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 to describe that", you need to comment it before you forget how it works. C style comments (%%/* */%%) are fine, but standard C++ comments (%%//%%) are preferred.

Including Code

Use require_once whenever possible, otherwise use require. Only libraries, classes, modules and templates should be included. All includes should, whenever possible, be placed at the top of the file before any functions, or operations are performed.

PHP Code Tags

Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. There are no exceptions to this rule.

File Formats

All scripts written must:

  • Be stored as ASCII text
  • Use UTF-8 character encoding

There should be no line feeds after the closing PHP tag (?>) to prevent output before headers are sent.

File Organization

In order to maintain some semblance of organization all files should be organized based on their function. refers to the top of the file path for the web server. All libraries should be located in /lib. Any additional modules that are suitable for separate distribution or anything not written by us should be put in /modules/. All HTML templates should be put in /templates. All images for the site should be under /images.

When naming files, in order to make it easy for others to figure out their purpose they should follow the following naming conventions. Library files should end in .lib.php. All PHP classes should be in their own distinct files which end in .class.php, except for abstract classes which end in .abstract.php. All HTML files which are conditionally included from other PHP scripts should end in .inc.php. The name of the file should represent what is contained within. Templates should match the function that calls them.

User Input

Special attention must be paid to user input. The general assumption must be made that every attempt will be made by the user to maliciously disrupt the script, or cause data loss when submitted to a database. User input includes information pulled from cookies which reside on the user's computer. All user input should be escaped and error checked before being used.

Database Connections and Calls

In order to not only ensure reliable database connections and data integrity but to account for future changes standardization of SQL statements and database calls is necessary. All SQL statements should use all capital letters for actual SQL commands and lowercase for field and table names when possible. All user inputted values should be escaped and all field names should be escaped using the correct escape character

/* Simple Query */
SELECT * FROM `user`;

/* Complex Query */
SELECT `user`.`id`, `preferences`.`value` FROM `user` 
    LEFT JOIN `preferences` ON `user`.`id` = `preferences`.`user`
    WHERE `user`.`username` = 'dude' AND `user`.`pass` = PASSWORD('mypassword')
    ORDER BY `user`.`id`
    LIMIT 5, 10;

Database Wrapper

All database queries should use Ampache's Dba wrapper rather than calling database functions directly.

// Query
$db_results = Dba::read('SELECT * FROM `user`);
return Dba::write('TRUNCATE `user`);

Version Compatibility

All PHP code written should work on PHP 5.3 or any newer version. All code should be written referencing the superglobals ($_POST, $_GET, and $_SERVER) as if 'register_globals' is off.

File and URL Paths

All file paths and URLs should be fully qualified and yet relational. $PHP_SELF should never be used.

// Generated URL using Web Path
$link = Config::get('web_path') . '/index.php';

// Include Statement using Prefix */
require_once Config::get('prefix') . '/templates/cool.inc.php';

HTML Output

All HTML written for Ampache should conform to W3C's XHTML 1 Transitional standards. All user input that is to be echoed out must be sanitized before being displayed to the screen.