src/ directory. Code in includes/ is legacy and does not necessarily comply.
File and folder layout
PSR-4 in src/
All classes under
src/ follow PSR-4 autoloading. The top-level namespace is SMW; every component lives in a sub-namespace matching its directory path.Legacy includes/
The
includes/ directory contains legacy code that pre-dates the PSR-4 layout. As classes gain sufficient test coverage they are migrated to src/. The long-term goal is to eliminate includes/ entirely.Namespace structure
Object interaction with MediaWiki classes (e.g.
Title, WikiPage, ParserOutput) must go through accessors in the SMW\MediaWiki namespace rather than being scattered across the codebase.PHP naming conventions
| Construct | Convention | Example |
|---|---|---|
| Classes | CamelCase in a namespace starting with SMW | SMW\Query\ResultPrinter |
| Methods and variables | camelCase starting with a lowercase letter | getPropertyValues(), $dataItem |
| Global functions | smwf prefix | smwfNormalTitleDBKey() |
| Global variables | smwg prefix | $smwgFixedProperties |
| Global constants | ALL_CAPS with SMW_ prefix | SMW_VERSION |
| Class constants | ALL_CAPS, no prefix required | DataItem::TYPE_NUMBER |
@private annotation
A class or method annotated with @private is restricted to internal use within SMW core. Even if the method has public visibility, external code must not rely on it — its signature or existence may change in any release.
Code layout
Method ordering
Methods inside a class are ordered by visibility to make the public contract immediately visible:General rules
- All files must be
UTF-8encoded with UNIX line endings. - Do not use a closing
?>tag. - Indent with tabs, not spaces.
- Always wrap single-statement blocks in
{ }. - Use
&&and||for logical operators, notandandor. - Write
true,false, andnullin lowercase. - Declare class members
privateby default; useprotectedonly when sub-class sharing is needed; usepublicto expose a method as part of the API.
Dependency injection
SMW strongly prefers dependency injection over inheritance and service location inside business logic.Factory pattern for instance creation
Allnew Foo(...) calls should be delegated to a factory service. Factories must not use conditional logic to decide which class to instantiate — conditionals belong in a builder or service locator.
Type hinting
Type hints must be used consistently on all new code, including method parameters, return types, and property declarations where supported by the minimum PHP version.Source documentation
Every class and public method must have a docblock using Doxygen notation:- Use
@sinceto record the version in which a method or hook was introduced. - Use
@todoand@buginline to track known issues without losing context. - Remove unused debug statements, variables, and functions before submitting a PR.
Testing requirements
- Unit tests
- Integration tests
- Behaviour switches
Unit tests cover a single class or method in isolation. They must not connect to a database or external service.Every new class and every new public method requires a corresponding unit test.
Running the full test suite locally
Git workflow
Target the master branch
All development happens against
master. Backports to maintenance branches are done by cherry-picking commits after they have merged into master.Send a first PR
Before submitting substantive changes, send a PR with the subject
[first pr] to verify your git setup and that you can replicate changes against master.Prepare your PR
Run
make composer-test locally and confirm all tests pass. If your PR introduces new behaviour, include tests that cover it before requesting review.Watch CI
Every PR triggers GitHub Actions across multiple MediaWiki and PHP versions. Review the output of failing jobs to identify the cause before pushing a fix.
JavaScript
JavaScript modules are registered with ResourceLoader viares/Resources.php. Global variables must carry the smw prefix. Use JSHint to catch potential errors before committing.