*/ private array $services = array(); public static function instance(): Plugin { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } private bool $notifiers_registered = false; private function __construct() {} /** * Fetch (and lazily build) a shared service instance. * * @param string $class Fully qualified class name. */ public function get( string $class ): object { if ( ! isset( $this->services[ $class ] ) ) { $this->services[ $class ] = new $class(); } return $this->services[ $class ]; } public function boot(): void { Migrations::maybe_upgrade(); ( new Listeners( new LedgerRepository() ) )->register(); ( new Cron() )->register(); ( new RumController( new SampleRepository() ) )->register(); ( new LabClient( new SampleRepository() ) )->register(); ( new LabScheduler() )->register(); ( new AvailabilityCheck() )->register(); $this->register_notifiers(); ( new WeeklyDigest() )->register(); // Admin bar shows on the front end too for logged-in administrators. ( new AdminBar() )->register(); ( new Privacy() )->register(); if ( is_admin() ) { ( new Menu() )->register(); ( new Onboarding() )->register(); ( new DashboardWidget() )->register(); ( new SiteHealth() )->register(); } CliCommands::register(); } /** * Notifications subscribe to incident lifecycle actions. Safe to call * more than once: a fatal error while plugins load opens its incident * before boot() has run, and registers the notifiers itself. */ public function register_notifiers(): void { if ( $this->notifiers_registered ) { return; } $this->notifiers_registered = true; ( new Emailer() )->register(); // The Slack and webhook notifiers live in the separate add-on plugin. if ( class_exists( Slack::class ) && class_exists( Webhook::class ) ) { ( new Slack() )->register(); ( new Webhook() )->register(); } } public function incidents(): IncidentRepository { return $this->get( IncidentRepository::class ); } public function ledger(): LedgerRepository { return $this->get( LedgerRepository::class ); } public function samples(): SampleRepository { return $this->get( SampleRepository::class ); } }