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.

Commenting examples
/**
 * A short one line description of the class
 *
 * You can now add a longer description and describe properties that might
 * be found via a magic get or set.
 *
 * @author Your Name <email@example.com>
 * @copyright Copyright (c) 2024 You or your employer
 */
class MyClass
{
	/** @var int A description of what the property stores. */
	protected int $property;

	/**
	 * A property that needs a long explanation
	 *
	 * If a property is complicated you may use a multi-line
	 * doc block for it.
	 *
	 * @var array
	 */
	protected array $data = [];

	/**
	 * A one line description of the method
	 *
	 * An optional longer description of the method if needed.
	 *
	 * You only need to to define @returns if you explicitly use
	 * a return statement.
	 *
	 * @param int $value A description of the value
	 */
	public function set_property(int $value)
	{
		$this->property = $value;
	}

	/**
	 * A one line description of the method
	 *
	 * An optional longer description of the method if needed.
	 *
	 * @returns int An optional text description what is returned when it is not already described.  
	 */
	public function get_property(): int
	{
		return $this->property;
	}
}


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
  • the main name of the file must be a lowercase version of the class name, for exmple if your class is called MyClass the filename would be myclass.class.php

We expect all classes in ExamSys to autoload

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.

Templates

Templates require some documentation to help people that want to make use of them

Example of template documentation
{#This file is part of ExamSys

ExamSys 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.

ExamSys 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 ExamSys. If not, see <http://www.gnu.org/licenses/>.
#}

{#
A one line description of the template.

You can optionally add more details about the template to help developers
understand how, when and why they might want to use it.

author Your name <email@example.com>
copyright 2024 onwards You or your employer

Required variables:

action - the form action
data - the form data

Required localised language strings -
lang.retention
lang.update
#}

We require that any data that the template uses is described

We also describe any language strings we expect in the template.

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.