Software quality
Basics
No globals
Do not use global variables like
$_POST
$_GET
$_SERVER
// etc.
To receive their represented values, use the methods provided by the shop framework, e.g.:
Registry::getRequest()->getRequestEscapedParameter($name, $defaultValue);
No global functions
Avoid creating new global functions (e.g. in the modules/functions.php
file).
No business logic in smarty functions
Use smarty only for design purposes. Business logic belongs to the PHP level.
PHP code
Object-oriented programming is highly preferred.
Make sure your code is compatible with the PHP versions described under Server and system requirements.
OXID standards
Module Structure
The module’s directory structure should be as described in modules/structure.
Module constituents
All modifications introduced by a module must be part of the module directory. This applies for theme extensions, such as blocks, new templates, as well as language files and resources. A module must not come with manual modification instructions for templates or language files of the core product or 3rd party modules.
Class design
Base extensions
Your classes should, in general, be – directly or indirectly – derived from the Base
(\OxidEsales\Eshop\Core\Base
)
class of the eShop framework. There are some exception where Base
does not have to be used:
in classes where lazy loading is not needed (not directly working with database)
new classes intended for working with the file system
But you must inherit from Base
,
when lazy loading is needed (for example like original shop file
Article
)whenever you want to be able to access the shop’s configuration
Getters and setters
Accessing public variables of the class should be implemented using getter and setter methods.
Do not use $this->_aViewData
In the shop’s frontend templates, and unless you are not working with admin templates, do not use
$this->_aViewData['someVar'] = 'some Value';
Instead, use
$this->addTplParam('someVar', 'some Value');
In general, keep in mind that setters and getters should be used whenever values are assigned to protected variables.
Exception handling
Create your own classes for exception handling and therefore use StandardException
:
use \OxidEsales\Eshop\Core\Exception\StandardException
Maximum length of methods < 80 lines
The number of lines of a method should not be higher than 80. The best practice is to stick with values below 40. Modules with more than 120 lines of code in a method cannot be certified.
Complexity
Maximum NPath complexity < 200
The NPath complexity is the number of possible execution paths through a method. Each control structure, e.g.
if
elseif
for
while
case
is taken into account also the nested and multipart boolean expressions. The NPath complexity should be lower than 200. Modules with values above 500 cannot be certified.
Maximum Cyclomatic Complexity = 4
The Cyclomatic Complexity is measured by the number of statements of
if
while
do
for
?:
catch
switch
case
as well as operators like
&&
||
and
or
xor
in the body of a constructor, method, static initializer, or instance initializer. It is a measure of the minimum number of possible paths through the source and therefore the number of required tests. In general, 1-4 is considered good, 5-7 ok, 8-10 means “consider re-factoring”, and 11 and higher tells you “re-factor now!”. A hard limit for the module certification process is a Cyclomatic Complexity of 8.
Maximum C.R.A.P. index < 30
The Change Risk Analysis and Predictions (C.R.A.P.) index of a function or method uses Cyclomatic Complexity and Code Coverage from automated tests to help estimate the effort and risk associated with maintaining legacy code. Modules with a CRAP index above 30 will not be accepted in the certification process.
Extending views and frontend
Module templates
Store all templates in the same structure as the shop templates are stored in.
For example:
views/
- all frontend templatesviews/admin_twig/
- all admin templates
For smarty:
views/admin_smarty/
- all admin templates
Smarty only
Register all new templates in metadata.php
, using the following naming convention:
[module_id]_[template_name].tpl
Using JavaScript and including .js files
Store JavaScript files in the following directories:
assets/js/libs
– if needs to define some additional JS librariesassets/js/widgets
– all newly created widgets
Use the following naming convention for new widgets:
[module_id]_[widget_name].js
Important
All Javascript code must be in files in the widgets folder.
Javascript code is not allowed directly in the template.
In the template, you are only allowed to do the assignment for widgets and do includes for the Javascript files you need.
To include Javascript files in the frontend, use the following expression:
{{ script({ include: oViewConf.getModuleUrl('[MODULE ID]', '[path where the needed file is]'), priority: 10 }) }}
And for output:
{{ script() }}
Assignment of a DOM element for a widget:
{{ script({ add: "const myModal = new bootstrap.Modal('#isRootCatChanged');myModal.show();" }) }}
In this way, Javascript files will be included correctly in the template.
Using CSS and including .css files
Store CSS files in: assets/css/<filename>
.
For CSS files, use the following naming convention: [module_id]_[css_file_name].css
To include a module’s custom CSS file, use the following expression:
{{ style({ include: oViewConf.getModuleUrl('module id', '[path where the needed file is]') }) }}
And for output:
{{ style() }}
Important
All required styles must be stored into CSS file and must not be assigned directly in the template.
Language files and templates
Make sure that individual language files and templates are stored in the module directory.
Appendix for Smarty
Template files
Naming convention:
[module_id]_[template_name].tpl
Blocks
Use block definitions in the templates.
This is not an obligation.
The naming convention for new blocks is:
[module_id]_[blockname]
.
In the templates, use blocks like the following:
[{block name="thevendor_themodule_theblock"}][{/block}]
Store all blocks information in the views/blocks
directory.
For example, if a block is intended for a certain file of a theme, like Application/views/[theme name]/tpl/page/details/details.tpl
, inside the module directory, the block file should be located in views/blocks/module_id_blockname.tpl
.
When adding contents for blocks in the admin interface, blocks should be located in paths like
views/blocks/admin/module_id_blockname.tpl
.
Use blocks whenever the shop’s functionality is extended to the frontend side and a requested function or method would not be available as long as the module is disabled.
Using blocks allows you to move function calls into small snippet files for the frontend that are only included when the modules is set active. Therefore, using blocks can be considered a quality feature of a module.
Including .js files
To include Javascript files in the frontend, use the following expression:
[{oxscript include=$oViewConf->getModuleUrl("[MODULE ID]", "js/[path where the needed file is] ") priority=10}]
And for output:
[{oxscript}]
Including .css files
To include a module’s custom CSS file, use the following expression:
[{oxstyle include=$oViewConf->getModuleUrl("module id", "css/{FileName}.css")}]
And for output:
[{oxstyle}]
Database access
Database access compatibility
Database access should be master-slave compatible.
For more information, see Database: Master/Slave.