Coding Standards

PHP


The implementation of this coding standard is on going. As the Rogo code base is some 18 years old the code base will take some time to be fully compliant. Contributors should focus on their own changes being compliant. If they would like to help making the older code compliant that would be appreciated.

CodeSniffer


It is recommended you set up your IDE to style check using code sniffer.

And example of how to set this up in PhpStorm is available here. Things you will need you will need to know:

Config ItemLocation
rule set

testing/codesniffer/Rogo/ruleset.xml (Existing code should have no errors in this, i.e. some strict errors are warnings here)

testing/codesniffer/Rogo/ruleset-strict.xml (New code should meet this standard)

code sniffervendor/squizlabs/php_codesniffer/bin/phpcs
code beautifiervendor/squizlabs/php_codesniffer/bin/phpcbf


The auto test environment uses code sniffer to ensure the code base meets the required coding standard.

auto test not currently set-up to analyse pull requests


PSR12


All PHP code should comply to the PSR12 standard with the following exceptions.


Exceptions to PSR12

Namespaces/Classes

  • Each class must be in a file by itself
  • Each class must be in a namespace of at least one level (a top-level vendor name)


Some existing classes do NOT follow PSR-0 so code sniffer will warn about it. However, new files will be expected to follow this standard and we should attempt to update existing code where possible.

Constants

  • Visibility must be declared on all constants as Rogo supports PHP 7.2 as a minimum

Strings

  • Variables are not allowed in double quoted string, concatenation should be used instead
  • String that do not require double quotes should use single quotes instead
  • Multi-line strings concatenations should should align 4 spaces indentation from the first line e.g.
    $string = 'a string '
        . 'a concat'
        . 'another concat';


Some existing strings use double quotes when not necessary and so code sniffer will warn about it. However, new files will be expected to follow this and we should attempt to update existing code where possible.

Boolean Operators

  • Boolean operators '&&' and '||' are prohibited, use the logical operators 'and' and 'or' instead.


Some existing control structures use boolean operators so code sniffer will warn about it. However, new files will be expected to follow this and we should attempt to update existing code where possible.

Code Documentation/Comments

  • Perl-style comments are not allowed
  • Files should not contain commented out code
  • Classes, Files and Functions
    • Must have phpdocs
    • Must use "/**" style comments
  • Files should start with the following Rogo boilerplate (unless 3rd party code)
 // This file is part of Rogō
 //
 // Rogō is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
 // the Free Software Foundation, either version 3 of the License, or
 // (at your option) any later version.
 //
 // Rogō 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.  See the
 // GNU General Public License for more details.
 //
 // You should have received a copy of the GNU General Public License
 // along with Rogō.  If not, see <http://www.gnu.org/licenses/>.
 

Some existing classes, files and functions have no docs, use a bad style, do not have a boilerplate or contain commented out code so code sniffer will warn about it. However, new files will be expected to follow this and we should attempt to update existing code where possible.

Page Parameters

  • $_GET, $_POST and $_REQUEST super globals must not be accessed directly. Instead values passed to them should be access via param::required(), param::optional() or check_var()

    • If param::required() is used the code must handle the exception that will occur if it is not set.

    • check_var() will automatically display a message and terminate the script if a required parameter is not present

    • param::optional() allows a value other than null to be returned if it is not set, so is recommended over check_var() for parameters that are not required.


Some existing code uses direct access so code sniffer will warn about it. However, new files will be expected to follow this and we should attempt to update existing code where possible.

Auto-loading

  • In order to be autoloaded classes must:
    • use the file extenstion '.class.php'
    • be located in any of the following locations:
      • <base dir>/classes
      • <base dir>/*/classes
      • <base dir>/plugins/*/classes

Files

PHP files should only contain php code.

Variable names

Names should be descriptive, but also concise. Wherever possible, keep variable names to under 15 characters, although be prepared to sacrifice a few extra characters to improve clarity. There’s no hard and fast rule when it comes to the length of a variable name, so just try and be as concise as possible without affecting clarity too much. Generally speaking, the smaller the scope of a variable, the more concise you should be, so global variables will usually have the longest names (relative to all others) whereas variables local to a loop might have names consisting only of a single character.

Error Reporting

Although it is good practice not to show PHP errors on a production server, Rogō should be written so that no errors occur when error reporting is set to E_ALL.

Things to Avoid

Globals

Where possible the use of global variables should be minimised. The $GLOBAL[] syntax should never be used.

Databases

SQL code layout

When writing SQL queries, capitialise all SQL keywords (SELECT, FROM, VALUES, AS etc.) and leave everything else in the relevant case.

SELECT title, first_name, family_name FROM users WHERE role = 'student' ORDER BY family_name;

Selects

Try to avoid the use of the wildcard to select all fields. Instead only return the relevant fields needed by the current script.

MySQLi Prepared Queries

For speed Rogō currently uses direct mysqli connections for speed and security. Use prepared queries following the object oriented style:

 $result = $mysqli->prepare("SELECT id, surname, intials, last_name FROM users WHERE id = ? LIMIT 1");
 $result->bind_param('i', $userID);
 $result->execute();
 $result->bind_result($id, $surname, $intials, $last_name);
 while ($result->fetch()) {
 
 }
 $result->close();

Putting values directly into SQL

If a variable cannot be passed to a query using bind_param() (for example a table or column name) the variable must be passed through param::clean() before it is used.

$original_paper_type = param::clean($original_paper_type, param::INT); // Paper type must always be an integer.
$sql = "SELECT id, q_id, user_answer, duration, screen, dismiss, option_order FROM log$original_paper_type WHERE metadataID = ?";

An exception can be made where a trustworthy source is the only thing that can provide the value, for example if the paper type was retrived from a paper properties object.

Unit tests

It is expected that all new features and bug fixes come with unittests.The caveat to this is if appropriate data generators do not exist. It which case it would be appreciated if these can be created. If this is not possible due to time constraints please inform the code reviewers.

Unit testing

Behat tests

It is expected that all new features and bug fixes come with behat tests. The caveat to this is if appropriate data generators or feature steps do not exist. It which case it would be appreciated if these can be created. If this is not possible due to time constraints please inform the code reviewers.

Behat testing


Javascript

See Javascript Modularisation

Minifaction

You should not submit any minimised javascript or css to the repository.

Javascript and css are minimised on the auto build environment. If you wish to build Rogo from source on your own development environment you will need to use Grunt to minify your js and css.


HTML

HTML should comply to the WCAG 2.1 standard at a minium.