Skip to content

Architecture

base-plugin is a Composer package (barberklingen/base-plugin) that other Barberklingen/Subscribed plugins require. It contains no WordPress plugin header — it is bootstrapped by the consuming plugin.

Namespace

All classes live under Barberklingen\BasePlugin\ with PSR-4 autoloading from src/.

Bootstrap

// 1. Build the League Container and register the global singleton
GlobalContainer::get_instance()->setup($container, new MyAppConfig());

// 2. Init core modules (migrations, admin hooks, renewals, staging CLI)
BasePluginSetup::get_instance()->init();

Directory structure

src/
├── DependencyManagement/   League Container wrapper + AppConfig interface
├── Migrations/             Database migration runner (versioned)
├── Modules/                Feature modules (see below)
├── Storage/                ORM-style base classes
├── Traits/                 Reusable traits (Module, Singleton, Scheduler, …)
├── Data/                   Frontend data-transfer objects
├── Frontend/               Asset enqueueing + template loading
├── Helpers/                Stateless utility classes
├── Http/                   HTTP controller base
├── REST/                   REST route base classes
├── Payments/               Payment handler contract
├── Staging/                CLI command for staging data pull
├── Exceptions/             Custom exception types
└── functions.php           Global helper functions

Dependency Injection

GlobalContainer wraps a League Container singleton. Consuming plugins call addProviders() to register their own service providers before modules are initialised.

AppConfig / AppConfigInterface carry environment-specific configuration (URLs, API keys, feature flags) and are bound to the container so any class can resolve them.

Migrations

Migrator (trait) runs versioned migrations on plugins_loaded. Each migration implements Migration and is listed in the migrator's get_migrations() array. The current version is stored in wp_options.

RecurringTasksMigrator registers WP-Cron schedules and recurring tasks.

Storage layer

Class / trait Purpose
BaseModel Active-record trait: save(), delegates to store
BaseStore CRUD operations against a custom DB table
ORMModel Extends BaseModel with typed property casting
ORMModelWithMeta Adds a MetaData side-table for arbitrary key/value pairs
LookupCache In-request cache for repeated store lookups

Key modules

Module Description
SubscriptionAddons Addon products attached to subscriptions; handles cart, renewals, admin UI, Klaviyo/GTM events
SubscriptionRenewals Custom renewal logic with status tracking; CLI command to cancel unpaid orders
ReferralCoupons Generate, list and validate referral coupons; WP-CLI commands
ReplacementOrder Replace an existing order via REST endpoint; Klaviyo extension
Security Role/capability management (customer service, finance, warehouse, etc.); area-based lockdown
Ajax/* AJAX checkout flow (setup → order/subscription), cart update, account actions
REST Base RouteController / RouteSchema for registering REST routes
Frontend Asset enqueueing, JS globals (GlobalAppJS), template rendering

Traits

Trait Description
Singleton get_instance() pattern
Module Calls init() from constructor; one-time initialisation guard
Scheduler Cron-job wrapper with distributed process lock (bypasses Redis object cache for the lock)
AjaxEndpoint Registers wp_ajax_* / wp_ajax_nopriv_* hooks
WCAPIEndpoint Registers WooCommerce REST routes

Scheduler flow

sequenceDiagram
    participant WP as WP-Cron
    participant S as Scheduler (trait)
    participant DB as wp_options (lock)

    WP->>S: system_cron_job_org action
    S->>S: maybe_start_scheduler()
    S->>DB: read lock directly (bypasses Redis cache)
    alt lock free
        S->>DB: set lock
        S->>S: scheduler_logic()
        S->>DB: release lock
    else already running
        S-->>WP: SchedulerAlreadyRunningException (NOOP)
    end