Writing code for Dokeos

Dokeos is a software programmed in PHP language. Here are a series of coding conventions to help you comply with common policies.

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. This also applies to bug reports and features requests.
Default conventions
When no convention below is more specific, we are using the PEAR 2 project's conventions to allow for better readability and re-usability of our code. You can find the PEAR 2 coding conventions here: http://pear.php.net/manual/en/pear2cs.php
require vs include
include and require are language constructs, not functions. Although they *do* work with parenthesis, the fact of adding the parenthesis actually makes PHP believe it is a function, and as such go through the additional process of trying to understand the function.
Please use:
require 'main/inc/global.inc.php';
don't use:
require('main/inc/global.inc.php');
When you get a chance to safely fix these in some script you are modifying, please do so.
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 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 realizing 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.
Some other large open-source projects, including Drupal, recommend not using the closing ?> tag at the end of a script. This is due to the fact that, if there are too many blank lines at the end of a script (more than one), after the closing tag, then your script will trigger the sending of HTTP headers to the user, preventing the system to send the appropriate redirect headers or other headers bound to the session (sending of cookies).
For example,
//comment $var = 123; ?> This code will send headers to the user although we are not at the end of the PHP process (there are still more scripts to be loaded in this chain), and consequently trigger the apparition of strange warning message, and the loss of the user's session. If you intentionally omit the closing tag (which in turn could trigger problems for parsing the PHP code through XML, but who does that?), then you ensure nothing will send blank lines to the user's browser, because the blank lines are considered as part of the PHP code and, as such, are ignored.
//comment $var = 123;
Note that PHP itself will automatically ignore *one* blank line after the closing PHP tag. Just one.
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<$a;$i++)
{
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.
This, however, is not what PEAR2 conventions require, which looks like this:
function something($a) {
for ($i=0;$i<$a;$i++) {
echo "$a
";
}
}
As a result, please respect the convention used through the file you are editing. You are also invited to respect the spacing required by PEAR2 in the conditional statements: a for statement will have, as in the last example, a space between for and the condition between parenthesis, then a space before the curly bracket {. This ensures easy differentiation between function-forms and conditional-statements-form (looking for a function's name ending with for will then be much easier because you will do it with the parenthesis included: for().
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.*)
Due to an uncontrolled past history of coding, a very large number of calls to mysql_query() are passed through the api_sql_query(). Although this is not really a *problem* in itself, we designer business cards are making efforts to see this function passed to Database::query() instead, to make sure everything related to the database layer will be handled by the Database class. If you are updating some code in Dokeos, please make sure you change all api_sql_query() calls to Database::query(), to ease the move to an abstraction layer in the future.
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.
CONSTANTS should always be in all-upper-case letters
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.
datetime, not timestamp
DO NOT APPLY YET. This is only a suggestion so far. Due to the Y2K38 bug, there is concern about whether timestamp fields should be changed to something more portable or not. http://en.wikipedia.org/wiki/Year_2038_problem If using datetime as database field to represent dates fixes the problem, then it should be applied all over the Dokeos code. This still has to be confirmed.
INT, not INT(11)
INT(11) is a markup created by phpMyAdmin in the automated table creation query generation, but is actually useless in the sense of PHP + MySQL. To be truly portable, declare INT fields as INT, not INT(11).
This is a quote from http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html:
The display width does not constrain the range of values that can be stored in the column, nor the number of digits that are displayed for values having a width exceeding that specified for the column. For example, a column specified as SMALLINT(3) has the usual SMALLINT range of -32768 to 32767, and values outside the range allowed by three characters are displayed using more than three characters.
INT UNSIGNED for primary and foreign keys
When declaring a primary or foreign key, please use the "UNSIGNED" qualifier. Although few of the current fields have been declared as unsigned, there is no use for the negative side of integers.
Unsigned integers, in MySQL, go from 0 to 4,294,967,295 (which is a considerably safe primary key allowance, given that MySQL starts to have problems dealing with new records over the 1,000,000,000 records without optimization)
Foreign keys implicit declaration
When declaring foreign keys in the database, the relation is considered implicit, and should be using the name "id" in the table where it acts as a primary key, and "[origintable]_id" in the table where it is used as a foreign key. The element type must be the same.
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/archive/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. custom home builders 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 movie editing programs 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.
Generally speaking, displayable text has to be filtered just before displaying it.
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. ebooks with resale rights 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().
api_get_setting('X') === 'true'
Due to a certain level of freedom added to the platform settings in the database, true and false values are written as 'true' and 'false' strings in the database. As a result, api_get_setting('X'), where X has a value of either true or false, will return 'true' or 'false', not TRUE or FALSE.
For this reason, these coding conventions include the fact that, when calling api_get_setting() on a boolean value, you compare it directly to the strings 'true' or 'false', and you do NOT use the if(api_get_setting('X')) form. Explicit, not implicit
.
