Ultimate Multisite is the user-facing product name. Use "Ultimate Multisite" in all
UI text, docs, and user-facing strings. The code namespace WP_Ultimo and the wu_
function/hook prefix are preserved for backwards compatibility — do not rename them.
WordPress Multisite WaaS plugin (formerly WP Ultimo). PHP 7.4+, WP 5.3+, GPL v2.
Root namespace: WP_Ultimo. Text domain: ultimate-multisite.
# Install dependencies
composer install && npm install
# Run full test suite (requires WP test environment — see bin/install-wp-tests.sh)
vendor/bin/phpunit
# Run a single test class
vendor/bin/phpunit --filter Cart_Test
# Run a single test method
vendor/bin/phpunit --filter test_constructor_initializes_defaults
# Run tests with coverage
php -d zend_extension=xdebug -d xdebug.mode=coverage vendor/bin/phpunit \
--coverage-html=coverage-html --coverage-clover=coverage.xml
# Lint PHP (PHPCS — WordPress coding standards)
vendor/bin/phpcs
vendor/bin/phpcbf # auto-fix
# Lint a single PHP file
vendor/bin/phpcs inc/path/to/file.php
vendor/bin/phpcbf inc/path/to/file.php
# Static analysis (PHPStan level 0)
vendor/bin/phpstan analyse
# Lint JS / CSS
npm run lint:js
npm run lint:css
# All quality checks
npm run check # lint + stan + testultimate-multisite.php # Plugin entry point, defines WP_ULTIMO_PLUGIN_FILE
constants.php # Plugin constants and feature flags
sunrise.php # MU-plugin for domain mapping (loaded before WP)
inc/
models/ # Data models (Base_Model subclasses)
managers/ # Singleton managers (business logic, hooks)
database/ # BerlinDB tables, schemas, queries, enums
gateways/ # Payment gateways (Stripe, PayPal, Manual, Free)
checkout/ # Cart, Checkout, Line_Item, signup fields
admin-pages/ # WP admin page controllers
list-tables/ # WP_List_Table subclasses
integrations/ # Host provider integrations (cPanel, Cloudflare, etc.)
functions/ # Procedural helper functions (wu_get_*, wu_create_*)
sso/ # Single sign-on across subsites
helpers/ # Utility classes (Arr, Hash, Validator, etc.)
apis/ # REST API, WP-CLI, MCP traits
ui/ # Frontend elements and shortcodes
traits/ # Shared traits (Singleton, deprecated compat)
exception/ # Runtime_Exception
tests/
WP_Ultimo/ # Unit tests mirroring inc/ structure
Admin_Pages/ # Admin page tests
e2e/ # Cypress E2E tests
bootstrap.php # WP test bootstrap (loads plugin via muplugins_loaded)
views/ # PHP template files
assets/ # JS, CSS, images, fonts
- Indentation: Tabs (not spaces). Tab width = 4.
- Braces: Opening brace on same line as declaration (
class Foo {,if (...) {). - Arrays: Short syntax
[]allowed. No spaces inside brackets:['key' => 'val']. - Ternary: Short ternary
?:allowed. - Yoda conditions: Required in production code (
'value' === $var). Not required in tests. - Strings: Single quotes preferred. Double quotes only when interpolating.
- Type hints: Use where present in existing code. NEVER add PHP return type
declarations (
: void,: string,: bool, etc.) to public methods on base/abstract classes or interfaces — external addons extend these classes and PHP will fatal if the child class doesn't declare the same return type. Use@returnPHPDoc tags instead. This applies to all classes ininc/gateways/,inc/ui/class-base-element.php,inc/models/class-base-model.php,inc/integrations/, andinc/checkout/. Private and final methods may use PHP return types freely. - PHPDoc: Required on classes and public methods in
inc/. Not required intests/. Every file header:@package WP_Ultimo,@subpackage,@since. - Security guard: Every PHP file starts with
defined('ABSPATH') || exit;. - i18n: All user-facing strings via
__(),esc_html__(), etc. with domainultimate-multisite. - Sanitization: Use
wu_clean()or WordPress sanitization functions. Custom sanitizers registered in.phpcs.xml.dist. - PHP compat: Must work on PHP 7.4+. Platform set to 7.4.1 in composer.json.
| Entity | Convention | Example |
|---|---|---|
| Classes | PascalCase |
Membership_Manager, Base_Model |
| Files (classes) | class-kebab-case.php |
class-membership-manager.php |
| Files (traits) | trait-kebab-case.php |
trait-singleton.php |
| Files (tests) | PascalCase_Test.php |
Cart_Test.php |
| Methods/functions | snake_case |
get_membership(), wu_get_site() |
| Global functions | wu_ prefix |
wu_get_membership(), wu_create_customer() |
| Constants | UPPER_SNAKE |
WP_ULTIMO_PLUGIN_DIR, WU_EXTERNAL_CRON_ENABLED |
| Hooks (actions/filters) | wu_ prefix |
wu_transition_membership_status |
| Capabilities | wu_ prefix |
wu_edit_settings, wu_read_dashboard |
| DB tables | {$wpdb->prefix}wu_ |
wp_wu_customers, wp_wu_memberships |
| Namespaces | WP_Ultimo\SubPackage |
WP_Ultimo\Models, WP_Ultimo\Checkout |
- WordPress ESLint config. Tabs for indentation. jQuery and Vue.js globals available.
camelCaseoff — snake_case allowed for WP compatibility.*.min.jsfiles are generated during the release build. Edit the non-minified source only and do not commit.min.jsfiles on feature branches.
- WordPress Stylelint config.
!importantallowed for admin overrides. *.min.cssfiles are generated during the release build. Edit the non-minified source only and do not commit.min.cssfiles on feature branches.
Managers use \WP_Ultimo\Traits\Singleton. Access via ::get_instance().
They define init() to register hooks. Never instantiate directly.
Extend Base_Model. Use BerlinDB for persistence. Access via wu_get_*() functions
or Model::get_by_id(). Models return false (not null) when not found.
Save with $model->save() which returns true or WP_Error.
Use WP_Error for validation/operation failures — not exceptions.
Runtime_Exception exists but is rarely used. Check is_wp_error() on return values.
- Extend
WP_UnitTestCase. Tests run in a WordPress Multisite environment (WP_TESTS_MULTISITE=1). - Test namespace mirrors source:
WP_Ultimo\Checkout\Cart_TesttestsWP_Ultimo\Checkout\Cart. - Use
wu_create_*()helper functions to set up test data. - Manager tests use
Manager_Test_Traitfor shared singleton/slug/model assertions. - Tests may use non-Yoda conditions, inline arrays, and skip PHPDoc.
- Direct DB queries (
$wpdb->query()) allowed in tests for setup/teardown.
The .githooks/pre-commit hook runs PHPCS + PHPStan on staged PHP files and
ESLint + Stylelint on staged JS/CSS. PHPCBF auto-fixes are attempted before failing.
Set up with: npm run setup:hooks or bash bin/setup-hooks.sh.
Indent with 2 spaces (not tabs). See .editorconfig.
The shared WordPress dev install for testing this plugin is at ../wordpress (relative to this repo root).
- URL: http://wordpress.local:8080
- Admin: http://wordpress.local:8080/wp-admin —
admin/admin - WordPress version: 7.0-RC2 (pre-release dev environment)
- This plugin: symlinked into
../wordpress/wp-content/plugins/$(basename $PWD) - Reset to clean state:
cd ../wordpress && ./reset.sh
WP-CLI is configured via wp-cli.yml in this repo root — run wp commands directly from here without specifying --path.
wp plugin activate $(basename $PWD) # activate this plugin
wp plugin deactivate $(basename $PWD) # deactivate
wp db reset --yes && cd ../wordpress && ./reset.sh # full DB + WordPress reset (requires reset.sh in ../wordpress)