Coding conventions
From Dokeos
Language
The code and comments and developer instructions you write should be in English, no matter what your native language is. It's great if manuals are available in many languages, but code with comments and variables in English, French and Spanish is hard to understand.
require() vs include()
An include() in PHP is the same as a require(), except that require() is more strict, meaning that if you try to include a file that does not exist, include() will generate a warning message, while require will generate a fatal error.
Unless you want to try out inclusion of some files, and you actually catch up the warning messages so you can deal with them, there's no reason at all to be using include(). include() obfuscate problems in your code, preventing you from realising that some of the libraries you are trying to use are not actually there. Sometime later, side-effects might appear because the file you are supposed to be including is not actually included but you don't know it.
Don't use include(), use require() instead!
Opening and closing php tags
Use the correct php tags: start with <?php and end with ?> . Do not use short tags <?, <?= or ASP-style tags <%, <%= as these rely on php.ini configuration settings (short_open_tag and asp_tags). These settings can cause errors when they are off and Dokeos code assumes that they are set to on.
The php.ini comments advise not to use short tags or ASP-style tags:
NOTE: Using short tags should be avoided when developing applications or libraries that are meant for redistribution, or deployment on PHP servers which are not under your control, because short tags may not be supported on the target server. For portable, redistributable code, be sure not to use short tags.
Whitespace
Adding a blank line between lines of code creates paragraphs of code and helps to visualize it. You don't want to read books that have a thousand pages filled with line after line and no breaks; nobody wants to read code like that either.
Also, using spaces around operators and after comma's can help to make the code more readable. However, most people write their function brackets without a space between the function name and the brackets:
function something(param a, param b) if ( (a
Use of brackets for loops
When declaring a function or opening a loop, put your opening brackets and closing brackets on an empty line, and at the same indentation
function something($a)
{
for($i=0;$i++:$i<$a)
{
echo "$a
";
}
}
This gives a very clear view of where a loop starts and where it finishes. Some code editors even improve this visibility by tracing a vertical line between the opening and the closing bracket.
Use of backticks
Backticks ( ` ) are a very bad MySQL-only habit. Don't use backticks at all. This will improve your respect of the SQL standard and make you find meaningful names for your tables and your fields, that will avoid them being misunderstood for a MySQL reserved keyword. When copy-pasting some code from phpMyAdmin, make sure you remove all backticks.
Use of PHP5
Although we have officially moved to PHP5 for Dokeos 1.8, most parts of Dokeos 1.8 still work with PHP4, so unless it is necessary or proves to be a big performance improvement, don't use PHP5 syntax uselessly in Dokeos 1.8. Dokeos 2.0 is heavily based on PHP5 and we encourage you to use PHP5-specific syntax to make class visibility clearer.
Use of internal functions
Try to use Dokeos' internal functions (API) as much as possible. There are three main libraries that you will need to review before starting to code with Dokeos: main_api.lib.php, database.lib.php and security.lib.php
The database library provides a complete abstraction layer that allows you to use all the necessary MySQL functions from Database:: prefixed static methods, to the exception of mysql_query(), that is replaced by api_sql_query(), defined in main_api.lib.php.
Don't use mysql_fetch_array(), but use Database::fetch_array() (in Dokeos 1.8.*)
Variable naming
Variable names inside Dokeos 1.8.* should always start with a lower-case character and be split by underscore characters (e.g. $my_little_variable). Camel-case names ($YourLittleVariable) are reserved for language variables.
Language variables should all use camel-case and start with an upper-case character.
time(), not NOW()
time() is a PHP function that generates a UNIX timestamp (the number of seconds from 1/1/1970 00:00:00 until now). NOW() is a MySQL function that generates a timestamp to the required format to fill the field it is put in.
Combining the two functions can lead to time matching problems, because time() depends on Apache and NOW() depends on MySQL server. These two programs can have different times (they can be on different servers or simply have a different configuration).
Because the process in Dokeos is based on PHP interpretation, time() must be used instead of NOW(), even when simply filling database logs fields. This will ensure that time-based values are all based on the same time source, and will make reliable statistical queries possible.
Error obfuscation
When using the @ symbol to obfuscate errors, make sure you check $php_errormsg (only available if php.ini track_errors setting is on) to deal with the error. In this specific case, adding a call to error_log() is an excellent idea, so that the error message is not "lost".
See the php documentation page for more info about this variable.
For example:
$res = @rmdir('/var/www/dokeos/main/garbage/ABC');
if($res === false)
{
error_log(__FILE__.' line '.__LINE__.': '.(ini_get('track_errors')!=false?$php_errormsg:'error not recorded because track_errors is off in your php.ini'));
}
Fatal, Warning and Notice -level error messages
We assume that any code you add to Dokeos will not generate Fatal nor Warning errors. You can try that by putting your portal in "test mode" in the configuration page. Notice-level error messages are accepted when submitting new code, but they are intended to disappear when the code is properly reviewed.
To show notice-level warnings, it is necessary to change the code of main/inc/global.inc.php to substitute E_ALL & ~E_NOTICE by E_ALL.
Security: Filter close to the database
Although the new object-oriented architecture of Dokeos 2.0 might improve this, there is no way to always be 100% sure that the variables entering one of your functions have been pre-filtered. It is thus mandatory to always make sure the data is filtered before being put in the database. To do this, always filter your data inside the function which is doing the database query. This way, you ensure your database is safe, no matter where the variables came from.
Security: Filter user input that has a chance to get on screen
XSS attacks are always based on using JavaScript to the user. What is less known is that a user can be directed to your site with a URL that includes JavaScript. In this case, the JavaScript can be executed with increased access due to the user's session. Although the effects are often damaging the user's experience rather than the website's safety, it is best to avoid the problem as much as possible.
A Security class is provided inside Dokeos 1.8.x which allows for filtering of several kinds of attacks. We ask you to make use of Security::remove_XSS() on any content that might contain JavaScript to show to the user. This includes messages generated from third party sources.
Security: CSRF
Cross-Site Request Forgery is also a mechanism by which JavaScript is abusing the user's browser. It is generally triggered from another website to benefit from the "open-session" effect that a user generates by staying "connected" to several sites at any one time. For example, a hackers site might use the user's session to connect to Dokeos and post spam content inside a course's description.
To avoid this, always make sure your forms are protected by a mechanism of controlled submission. The Security class can help you do that, particularly Security::get_token() and Security::check_token().

