-
Notifications
You must be signed in to change notification settings - Fork 6
Papaya_CMS_Coding_Standards
Commit Messages
All messages should wrap at 79 characters per line. This means, if you are writing multiple lines after a message starting with a "- " each following line should be indented by exactly two spaces. Including descriptive text in your commit messages is generally important to offer a good overview on the commit when the issue tracker is not available (commit mails, history).
All messages may include references to existing issues to add status updates to the issue, which should look like:
- Refs MANTIS-<number>: <text>
Where references the ticket and the describes what you did. The ticket numer has no leading zeros.
Keyword | Ticket | Usage |
---|---|---|
Added | no | Added file, class, method, ... |
Documented | optional | Added or changed source documentation |
Fixed | yes | Fixed a bug |
Implemented | optional | Implemented some new logic/feature |
Refs | yes | Reference to a bug ticket. This commit has dependencies to the ticket. |
Tested | no | Added unit/integration test for classes/methods |
Translated | no | Translated some text |
- Added: PapayaCommitMessageParser for commit message checks
- Fixed MANTIS-10815: because it was here and should not
You may always append arbitrary comments in your commit messages, where each line should start with a number sign (#). Text in these lines won't be checked.
A bug fix commit message should follow the following scheme::
- Fixed MANTIS-<number>: <text>
Where references the closed bug and is a description of the bug and the fix. Keep in mind that the texts will be used for the changelog, so please check the spelling before committing.
The bug number is not optional, which means that there should be an open bug in the issue tracker for *each* bug you fix.
For compatibility with other issue tracker you may also use "Closed" instead of "Fixed" in your message, but "Fixed" is highly preferred.
If you implemented a new feature, your commit message should look like::
- Implemented[ MANTIS-<number>]: <text>
Where is a short description of the feature you implemented, and may optionally reference a feature request in the bug tracker. Keep in mind that the texts will be used for the changelog, so please check the spelling before committing.
If you extended your documentation, your commit message should look like::
- Documented[ MANTIS-<number>]: <text>
Where optionally specifies a documentation request, and the text describes what you documented.
If you added tests for some feature, your commit message should look like::
- Tested: <text>
Where describes the feature(s) you are testing.
If your commit does not match any of the above rules you should only include a comment in your commit message or extend this document with your commit message of desire.
Message ::= Statement+ | Statement* Comment+
Statement ::= Reference | Fixed | Implemented | Documented | Tested
| Added | Translated
Comment ::= '# ' TextLine | '#\n'
Reference ::= '- Refs' BugNr ': ' TextLine Text?
Fixed ::= '- ' FixedString BugNr ': ' TextLine Text?
Implemented ::= '- Implemented' BugNr? ': ' TextLine Text?
Documented ::= '- Documented' BugNr? ': ' TextLine Text?
Tested ::= '- Tested: ' TextLine Text?
Added ::= '- Added: ' TextLine Text?
Translated ::= '- Translated: ' TextLine Text?
FixedString ::= 'Fixed' | 'Closed'
Text ::= ' ' TextLine Text?
BugNr ::= ' MANTIS-' [1-9]+[0-9]*
TextLine ::= [\x20-\x7E]+ "\n"
Encoding
Use only ASCII chars in your PHP source documents. If you need to write chars in other encodings use escaping (in PHP strings/constants) or translitaration (in comments or names).
define(
'PAPAYA_CHECKIT_WORDCHARS',
"\xc3\x80-\xc3\x8f\xc3\x91-\xc3\x96\xc3\x98-\xc3\xb6\xc3\xb8-\xc3\xbf"
);
The language of the PHP source documents is English, do not use other languages for names or comments.
Indent / Line Length
Use an indent of 2 spaces, with no tabs. It is recommended that you break lines at approximately 100 characters. There is no standard rule for the best way to break a line, use your judgment and, when in doubt, ASK.
If your editor can be configured to remove spaces from the end of a line when you save a file, please do so. This prevents unnecessary differences in file versions.
Control Structures
These include if
, for
, while
, switch
, etc. Here is an example if
statement, since it is the most complicated of them:
<?php
if ((condition1) || (condition2)) {
action1();
} elseif ((condition3) && (condition4)) {
action2();
} else {
defaultaction();
}
?>
If a condition is too long, it is suggested to break it after any boolean operator (||
, &&
) for faster comprehension.
Use of abbreviated if
statments is acceptable if really short, i.e. it doesn't exceed line limit:
$selected = ($foo == $bar) ? ' selected="selected"' : '';
Control statements should have one space between the control keyword and opening parenthesis, to distinguish them from function calls.
You are strongly encouraged to 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:
<?php
switch (condition) {
case 1:
action1;
break;
case 2:
action2;
break;
default:
defaultaction;
break;
}
?>
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:
<?php
$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, do not add more spaces!
<?php
$short = foo($bar);
$longVariable = foo($baz);
?>
If parameter string of a function call is to long for a single line break after the first ( and before the last. If it is still to long break after each parameter.
<?php
$singleLineBreak = foo(
$parameterOne, $parameterTwo, $parameterTree
);
$parameterLineBreak = foo(
$parameterOne,
$parameterTwo,
$parameterTree,
$parameterFour,
$parameterFive
);
$nestedFunctionsBreak = fooBar(
bar(
foo(
$parameterOne, $parameterTwo, $parameterTree
.md)
.md),
$fooBarParameter
);
?>
Function Definitions
Function definitions are formatted like control stuctures:
<?php
function fooFunction($arg1, $arg2 = '') {
if (condition) {
statement;
}
return $val;
}
?>
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.
Comments
Complete inline documentation (in English) comment blocks (docblocks, see phpdocumentor) must be provided.
Mandatory elements for classes/files are @package, @version
The @author element must not be included in the docbook comment. We use the version control system to identifify the authors.
Non-documentation 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.
C style comments (* */) and standard C++ comments (/) are both fine. Use of Perl/shell style comments (#) is discouraged.
Including Code
Anywhere you are unconditionally including a class file, use require_once. Anywhere you are conditionally including a class file (for example, factory methods), use include_once. Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with require_once will not be included again by include_once.
If the included file is a part of the base system use the PAPAYA_INLUDE_PATH
. If the File is a part of the same module use dirname(__FILE__)
. In all other cases ASK.
Note: include_once and require_once are statements, not functions. It is not nessesary, but please always surround the subject filename with parentheses.
<?php
require_once(PAPAYA_INCLUDE_PATH.'system/sys_base_object.php');
include(dirname(__FILE__).'/foobar.php');
?>
PHP Code Tags
Always use to delimit PHP code, not the ?> shorthand and not the <% %> ASP style.
Naming Conventions
Only use English and ASCII letters (no digits or special chars please). Avoid using abbreviations where possible.
Classes should be given descriptive names. Class names should always be uppercase, and their names should reflect the subdirectory structures they're located in, where each new word refers to a subdirectory (for example, a class called PageDatabaseAccess should be called Access.php and be located in a subdirectory structure called Page/Database). Parts are separated using the "studly caps" style (also referred to as "bumpy case" or "camel caps").
<?php
class FooBar {
}
?>
Functions and methods should be named using the "studly caps" style (also referred to as "bumpy case" or "camel caps"). Functions (not methods) should in addition have the module name as a prefix, to avoid name collisions between modules. The initial letter of the name (after the prefix) is lowercase, and each letter that starts a new "word" is capitalized. Some examples:
- $this->insertRecord()
- $this->databaseQueryFmt()
Functions and methods should be named using the "studly caps" style (also referred to as "bumpy case" or "camel caps"). The initial letter of the name (after the prefix) is lowercase, and each letter that starts a new "word" is capitalized. Some examples:
- $fooBar
- $this->fooBar
Private class members (meaning class members that are intended to be used only from within the same class in which they are declared) are preceded by a single underscore. Some examples:
- private $_fooBar
- $this->_fooBar
Note: This rule does not apply to global variables.
Global Variables should be all-uppercase, with underscores to separate words. Please ASK before defining global variables.
Constants should always be all-uppercase, with underscores to separate words. Prefix constant names with the uppercased name of the module/package they are used in. Please ASK before defining constants.
-
TRUE
-
FALSE
-
NULL
-
PAPAYA_INCLUDE_PATH<
Always use lowercase ASCII letters separated by underscores.
- table_name
- field_name
Use the same convention as for database fields, i.e. lowercase with underscores.
array(
'some_value' => 10,
'some_other_value' => 'id',
);
Always use uppercase ASCII letters separated by underscores.
- $this->records[$id]['TRANSLATION']
- $this->records[$id]['PARENT_IDS']
Always use lowercase ASCII letters separated by underscores.
- paramname
- paramname_sub
Separate words of elements (tag names and attribute names) by a dash '-'. Exception: XML that goes into Flash. Use an underscore in that case, since the Flash XML parser is allergic to tagnames with a dash, it would die if you used it.
<my-element-name my-attribute-name="somevalue" />
If you have a variable returned at the end of a function/method, name this variable $result
.
Default Class Template
Please use the following default class template. A constructor is only necessary if the class is not derived or something has to be initialized at construction of the object.
<?php
/**
* {%SHORT_CLASS_DESCRIPTION%}
*
* @copyright 2002-2010 by papaya Software GmbH - All rights reserved.
* @link http://www.papaya-cms.com/
* @licence GNU General Public Licence (GPL) 2 http://www.gnu.org/copyleft/gpl.html
*
* You can redistribute and/or modify this script under the terms of the GNU General Public
* License (GPL) version 2, provided that the copyright and license notes, including these
* lines, remain unmodified. papaya is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.
*
[*
* {%LONGER_DESCRIPTION_IF_NECESSARY%} ]
*
* @package {%PACKAGE_NAME%}
* @subpackage {%SUBPACKAGE_NAME%}
* @version $Id$
*/
{%NECESSARY_INCLUDES_AND_DEFINES_GO_HERE%}
/**
* {%SHORT_CLASS_DESCRIPTION%}
*
* @package {%PACKAGE_NAME%}
* @subpackage {%SUBPACKAGE_NAME%}
*/
class {%CLASSNAME%} [extends {%PARENTCLASS%}] {
/**
* @var {%ATTRIBUTE_TYPE%} ${%ATTRIBUTE_NAME%} {%ATTRIBUTE_DESCRIPTION%}
*/
public|protected|private ${%ATTRIBUTE_NAME%} [= {%DEFAULT_VALUE%}];
/**
* {%METHOD_DESCRIPTION%}
[ *
* {%LONGER_DESCRIPTION_IF_NECESSARY%} ]
*
* @since {%FIRST_PAPAYA_CMS_VERSION_CONTAINING_THIS_METHOD%}
[ * @param {%PARAMETER_TYPE%} $parameter {%DESCRIPTION_OF_PARAMETER%} ]
[ * @return {%RESULT_TYPE%} {%DESCRIPTION_OF_RESULT%} ]
*/
function __construct([$parameter [= {%DEFAULT_VALUE%}]]) {
parent::__construct([$parameter]);
// HERE GOES ALL THE INITIALIZATION STUFF
}
function {%CLASSNAME%}([$parameter [= {%DEFAULT_VALUE%}]]) {
$this->__construct([$parameter [= {%DEFAULT_VALUE%}]]);
}
{%MORE_METHODS%}
}
?>
Strings
Enclose strings using ' except the string contains many ' - as in SQL - or char codes (\n , \t, ...)
Enclose regular expressions with brackets: '(EXPR)'.
SQL
Enclose SQL-Strings in double quotes ("). The single quote (') is used for strings inside SQL. Write reserved words and SQL functions uppercase. Insert spaces to align the first word of each line. Never use an asterisk (*) to fetch all fields, state each field explicitely.
SELECT t1.field1, t2.field2
COUNT(t2.field3) fieldalias
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON (t1.field1 = t1.field2)
WHERE field2 = 'value'
GROUP BY t1.field1, t2.field2
ORDER BY t1.field1 DESC, t2.field2 ASC
Escape all variables inserted in SQL queries. Use $db->databaseGetSQLCondition()
for conditions, use $db->databaseQueryFmt($sql, $params)
for all other values and use $db->escapeStr()
if the previous methods are not possible.
Example:
$condition = $this->databaseGetSQLCondition('item_type', $this->params['item_type']);
$sql = "SELECT item_id, item_name, item_type
FROM %s
WHERE $condition
AND item_id <= %s";
$params = array($this->tableItems, (int)$this->params['max_id']);
if ($this->databaseQueryFmt($sql, $params)) {
while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
$result[$row['item_id']] = $row;
}
}
If you have to build your own UPDATE or INSERT queries and cannot use databaseInsertRecord or databaseUpdateRecord, make sure you call databaseQueryFmtWrite OR databaseQueryWrite to provide compatibility on multi-database installations.
If a query uses more than one table or database, use aliases. All field and table names must be prefixed by the correct alias.
CSS
CSS class names should be named using the "studly caps" style (also referred to as "bumpy case" or "camel caps"). The initial letter of the name (after the prefix) is lowercase, and each letter that starts a new "word" is capitalized. The class names should be semantic and without any "layout information".
Each attribute must be on a separate line. After the colon a space is required. The semicolon after the last attribute may not be left out.
For consistency using hexadecimal RGB value (#3399FF) for colors is suggested. Most designers won't ever pick a named color anyway. The shorthand #RGB (e.g. #FFF for #FFFFFF or #900 for #990000) may be used as well.
Some examples:
additionalContent {
width: 100px;
color: #333333;
}
contentSubTitle {
}
Sizes should be in em and px. Do not use pt, except in print stylesheets.
XSLT
Named templates are preferred, avoid match templates if possible.
XSLT template names should be named using only lowercase letters separated by minus. Standard XSLT functions/structures are always lowercase seperated by minus. Our custom template names and function names match that style.
XSLT local variable and parameters names should be named using the "studly caps" style (also referred to as "bumpy case" or "camel caps"). The initial letter of the name (after the prefix) is lowercase, and each letter that starts a new "word" is capitalized.
Global XSLT variable names should be named using uppercase letters seperated by underscores.
<xsl:template name="format-date">
<xsl:param name="date" />
<xsl:param name="format" select="$DATETIME_DEFAULT_FORMAT" />
<xsl:call-template name="format-date-time">
<xsl:with-param name="dateTime" select="$date" />
<xsl:with-param name="format" select="$format" />
<xsl:with-param name="outputTime" select="false()" />
</xsl:call-template>
</xsl:template>