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 Item | Location |
---|---|
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 sniffer | vendor/squizlabs/php_codesniffer/bin/phpcs |
code beautifier | vendor/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.
/** * 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
{#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.
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.
Javascript
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.