Coding style
ShopClass core follows PSR-12, enforced by a pinned php-cs-fixer that CI
runs on every pull request. You do not have to memorise the rules — run the
formatter.
Running the formatter
Section titled “Running the formatter”composer cs:check # dry run with a diff — exactly what CI enforcescomposer cs:fix # applyThe ruleset is deliberately non-risky: only whitespace, structure and import
hygiene are touched, never anything that could change runtime behaviour.
Generated and vendored trees — oc-includes/vendor, oc-includes/assets,
oc-content, oc-includes/osclass/gui — are excluded because they are not ours
to reformat.
Checking the PHP floor
Section titled “Checking the PHP floor”The supported floor is PHP 8.0, and CI fails a pull request that uses syntax or functions newer than that — even if your local PHP is happy with it:
composer lint:install # oncecomposer compatcomposer lint # cs:check + compat togetherComposer’s config.platform is pinned to 8.0.0, so a dependency requiring more
is refused at resolution rather than at runtime on somebody’s shared host.
Editor setup
Section titled “Editor setup”The repository has an .editorconfig; most editors pick it up automatically.
| Setting | Value |
|---|---|
| Indentation | 4 spaces (2 for scss, css, json, yml) |
| Line endings | LF |
| Encoding | UTF-8 |
| Final newline | required |
| Trailing whitespace | trimmed (except in Markdown) |
What PSR-12 gives you
Section titled “What PSR-12 gives you”The rules you will notice most:
<?php
namespace mindstellar\example;
class Foo{ public function bar(int $count): string { if ($count !== 2) { $count = 2; } elseif ($count === 3) { $count = 4; } else { $count = 7; }
return (string) $count; }}- Full
<?phptags always; short tags never. In a file that is only PHP, omit the closing tag. - The class brace goes on its own line; a method brace on its own line; a control-structure brace on the same line.
- Always use braces, even for a one-line body.
if ($a) $a = 2;is not valid here. - Never omit
defaultfrom aswitch. - Imports sorted alphabetically, unused ones removed.
Legacy conventions you will meet
Section titled “Legacy conventions you will meet”Core is two decades old in places, and the fixer does not rename anything. Older files use Hungarian notation for variables:
$iThisIsAnInteger = 42;$sSomeText = 'This is some text';$aVariable = array(1, 2, 3);New code does not need to adopt it — write plain, descriptive names — but do not rewrite existing variables just to change their style. A rename that touches a hundred lines hides the one line that mattered.
Database column names, however, are a live convention, not legacy. They carry a type prefix after an underscore, lowercase, words separated by underscores:
i_integer_columns_some_textd_priceb_enableddt_registration_datepk_i_id -- primary keyfk_i_category_id -- foreign keyFollow it in any table you add — the DAO layer and the schema reconciler both assume it.
Documentation blocks
Section titled “Documentation blocks”Public functions and classes carry a phpDocumentor-compatible docblock. Say what is not obvious from the signature; do not restate the parameter types the signature already gives.
What you must not rename
Section titled “What you must not rename”ShopClass runs on installs with third-party themes and plugins. The osc_*
helper functions, hook names, admin CSS class names and oc-includes/assets/
paths are a public API. Restyle freely; do not rename or remove them.