container = new Container(); } /** * Returns the plugin instance. * * @since 0.1.0 * * @return Plugin */ public static function instance(): self { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Returns the service container. * * @since 0.1.0 * * @return Container */ public function container(): Container { return $this->container; } /** * Registers services and hooks them into WordPress. Runs once on `plugins_loaded`. * * @since 0.1.0 * * @return void */ public function boot(): void { if ( $this->booted ) { return; } $this->booted = true; $this->register_services(); foreach ( $this->hookable_services() as $id ) { $service = $this->container->get( $id ); if ( $service instanceof Hookable ) { $service->register(); } } /** * Fires once the plugin has finished booting. * * @since 0.1.0 * * @param Plugin $plugin Plugin instance. */ do_action( 'hostkhata_loaded', $this ); } /** * Defines every service the plugin knows about. * * @return void */ private function register_services(): void { $c = $this->container; // Infrastructure. $c->singleton( I18n::class, static function () { return new I18n(); } ); $c->singleton( Settings::class, static function () { return new Settings(); } ); $c->singleton( Logger::class, static function ( Container $c ) { return new Logger( $c->get( Settings::class ) ); } ); $c->singleton( Capabilities::class, static function () { return new Capabilities(); } ); // Database and lifecycle. $c->singleton( Migrator::class, static function () { return new Migrator( $GLOBALS['wpdb'] ); } ); $c->singleton( Installer::class, static function ( Container $c ) { return new Installer( $c->get( Migrator::class ), $c->get( Capabilities::class ), $c->get( Logger::class ) ); } ); $c->singleton( Upgrader::class, static function ( Container $c ) { return new Upgrader( $c->get( Installer::class ) ); } ); // Security. $c->singleton( OwnershipRepository::class, static function () { return new OwnershipRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( Gate::class, static function ( Container $c ) { return new Gate( $c->get( OwnershipRepository::class ) ); } ); $c->singleton( RateLimiter::class, static function () { return new RateLimiter(); } ); $c->singleton( LoginGuard::class, static function ( Container $c ) { return new LoginGuard( $c->get( CustomerRepository::class ) ); } ); // Customers. $c->singleton( CustomerRepository::class, static function () { return new CustomerRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( ContactRepository::class, static function () { return new ContactRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( NoteRepository::class, static function () { return new NoteRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( ActivityRepository::class, static function () { return new ActivityRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( CustomerService::class, static function ( Container $c ) { return new CustomerService( $c->get( CustomerRepository::class ), $c->get( ContactRepository::class ), $c->get( NoteRepository::class ), $c->get( ActivityRepository::class ), $c->get( OwnershipRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( CustomerPrivacy::class, static function ( Container $c ) { return new CustomerPrivacy( $c->get( CustomerRepository::class ), $c->get( ContactRepository::class ), $c->get( NoteRepository::class ), $c->get( ActivityRepository::class ), $c->get( CustomerService::class ) ); } ); $c->singleton( Registration::class, static function ( Container $c ) { return new Registration( $c->get( CustomerService::class ), $c->get( Settings::class ), $c->get( RateLimiter::class ) ); } ); // Catalogue, tax and coupons. $c->singleton( GroupRepository::class, static function () { return new GroupRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( ProductRepository::class, static function () { return new ProductRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( TaxRateRepository::class, static function () { return new TaxRateRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( CouponRepository::class, static function () { return new CouponRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( CatalogService::class, static function ( Container $c ) { return new CatalogService( $c->get( GroupRepository::class ), $c->get( ProductRepository::class ) ); } ); $c->singleton( TaxService::class, static function ( Container $c ) { return new TaxService( $c->get( TaxRateRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( CouponService::class, static function ( Container $c ) { return new CouponService( $c->get( CouponRepository::class ) ); } ); $c->singleton( ProductsShortcode::class, static function ( Container $c ) { return new ProductsShortcode( $c->get( ProductRepository::class ), $c->get( Settings::class ) ); } ); // Orders, hosting and domains. $c->singleton( Sequence::class, static function () { return new Sequence( $GLOBALS['wpdb'] ); } ); $c->singleton( OrderRepository::class, static function () { return new OrderRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( ServiceRepository::class, static function () { return new ServiceRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( DomainRepository::class, static function () { return new DomainRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( ActivityLogger::class, static function ( Container $c ) { return new ActivityLogger( $c->get( ActivityRepository::class ) ); } ); $c->singleton( ServiceService::class, static function ( Container $c ) { return new ServiceService( $c->get( ServiceRepository::class ), $c->get( CustomerRepository::class ), $c->get( ProductRepository::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( DomainService::class, static function ( Container $c ) { return new DomainService( $c->get( DomainRepository::class ), $c->get( CustomerRepository::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( OrderPlanner::class, static function ( Container $c ) { return new OrderPlanner( $c->get( ProductRepository::class ), $c->get( OrderRepository::class ), $c->get( TaxService::class ), $c->get( CouponService::class ), $c->get( Settings::class ) ); } ); $c->singleton( OrderService::class, static function ( Container $c ) { return new OrderService( $c->get( OrderRepository::class ), $c->get( OrderPlanner::class ), $c->get( CustomerRepository::class ), $c->get( CouponRepository::class ), $c->get( ActivityLogger::class ), $c->get( Sequence::class ), $c->get( Settings::class ) ); } ); $c->singleton( FulfilmentService::class, static function ( Container $c ) { return new FulfilmentService( $c->get( OrderRepository::class ), $c->get( OrderService::class ), $c->get( ServiceService::class ), $c->get( DomainService::class ), $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( ImportService::class, static function ( Container $c ) { return new ImportService( $c->get( ServiceService::class ), $c->get( DomainService::class ), $c->get( CustomerRepository::class ), $c->get( ProductRepository::class ), $c->get( Settings::class ) ); } ); // Billing. $c->singleton( InvoiceRepository::class, static function () { return new InvoiceRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( PaymentRepository::class, static function () { return new PaymentRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( CreditRepository::class, static function () { return new CreditRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( InvoiceService::class, static function ( Container $c ) { return new InvoiceService( $c->get( InvoiceRepository::class ), $c->get( OrderRepository::class ), $c->get( OrderService::class ), $c->get( CustomerRepository::class ), $c->get( CreditRepository::class ), $c->get( ActivityLogger::class ), $c->get( Sequence::class ), $c->get( Settings::class ) ); } ); $c->singleton( PaymentService::class, static function ( Container $c ) { return new PaymentService( $c->get( PaymentRepository::class ), $c->get( InvoiceRepository::class ), $c->get( InvoiceService::class ), $c->get( CreditRepository::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( CreditService::class, static function ( Container $c ) { return new CreditService( $c->get( CreditRepository::class ), $c->get( CustomerRepository::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( InvoicePresenter::class, static function ( Container $c ) { return new InvoicePresenter( $c->get( PaymentRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( InvoiceDocument::class, static function ( Container $c ) { return new InvoiceDocument( $c->get( InvoiceRepository::class ), $c->get( CustomerRepository::class ), $c->get( InvoicePresenter::class ), $c->get( Settings::class ), $c->get( RateLimiter::class ), $c->get( Gate::class ) ); } ); $c->singleton( OrderForm::class, static function ( Container $c ) { return new OrderForm( $c->get( OrderService::class ), $c->get( ProductRepository::class ), $c->get( CustomerRepository::class ), $c->get( Settings::class ), $c->get( RateLimiter::class ) ); } ); // Email, reminders and notices. $c->singleton( EmailRepository::class, static function () { return new EmailRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( ReminderRepository::class, static function () { return new ReminderRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( NoticeRepository::class, static function () { return new NoticeRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( EmailTemplates::class, static function () { return new EmailTemplates(); } ); $c->singleton( EmailRenderer::class, static function ( Container $c ) { return new EmailRenderer( $c->get( EmailTemplates::class ), $c->get( Settings::class ) ); } ); $c->singleton( EmailVars::class, static function ( Container $c ) { return new EmailVars( $c->get( Settings::class ), $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ) ); } ); $c->singleton( Mailer::class, static function ( Container $c ) { return new Mailer( $c->get( EmailTemplates::class ), $c->get( EmailRenderer::class ), $c->get( EmailRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( QueueRunner::class, static function ( Container $c ) { return new QueueRunner( $c->get( EmailRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( EmailEvents::class, static function ( Container $c ) { return new EmailEvents( $c->get( Mailer::class ), $c->get( EmailVars::class ), $c->get( CustomerRepository::class ), $c->get( OrderRepository::class ), $c->get( InvoiceRepository::class ), $c->get( PaymentRepository::class ) ); } ); $c->singleton( ReminderService::class, static function ( Container $c ) { return new ReminderService( $c->get( ReminderRepository::class ) ); } ); $c->singleton( ReminderRunner::class, static function ( Container $c ) { return new ReminderRunner( $c->get( ReminderRepository::class ), $c->get( ReminderService::class ), $c->get( Mailer::class ), $c->get( EmailVars::class ), $c->get( CustomerRepository::class ), $c->get( InvoiceRepository::class ), $c->get( DomainRepository::class ), $c->get( ServiceRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( NoticeService::class, static function ( Container $c ) { return new NoticeService( $c->get( NoticeRepository::class ), $c->get( CustomerRepository::class ), $c->get( Mailer::class ), $c->get( EmailVars::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( EmailTemplatesController::class, static function ( Container $c ) { return new EmailTemplatesController( $c->get( EmailTemplates::class ), $c->get( EmailRenderer::class ), $c->get( Mailer::class ), $c->get( QueueRunner::class ), $c->get( EmailVars::class ) ); } ); $c->singleton( EmailsController::class, static function ( Container $c ) { return new EmailsController( $c->get( EmailRepository::class ), $c->get( QueueRunner::class ) ); } ); $c->singleton( ReminderRulesController::class, static function ( Container $c ) { return new ReminderRulesController( $c->get( ReminderService::class ), $c->get( ReminderRepository::class ), $c->get( ReminderRunner::class ) ); } ); $c->singleton( NoticesController::class, static function ( Container $c ) { return new NoticesController( $c->get( NoticeService::class ), $c->get( NoticeRepository::class ) ); } ); // Recurring billing. $c->singleton( RenewalService::class, static function ( Container $c ) { return new RenewalService( $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ), $c->get( InvoiceRepository::class ), $c->get( InvoiceService::class ), $c->get( ProductRepository::class ), $c->get( CustomerRepository::class ), $c->get( TaxService::class ), $c->get( ActivityLogger::class ), $c->get( Settings::class ) ); } ); $c->singleton( LateFeeService::class, static function ( Container $c ) { return new LateFeeService( $c->get( InvoiceRepository::class ), $c->get( InvoiceService::class ), $c->get( Settings::class ) ); } ); $c->singleton( SuspensionService::class, static function ( Container $c ) { return new SuspensionService( $c->get( InvoiceRepository::class ), $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ), $c->get( ActivityLogger::class ), $c->get( Settings::class ) ); } ); $c->singleton( PlanChangeService::class, static function ( Container $c ) { return new PlanChangeService( $c->get( ServiceService::class ), $c->get( ServiceRepository::class ), $c->get( ProductRepository::class ), $c->get( CustomerRepository::class ), $c->get( RenewalService::class ), $c->get( InvoiceService::class ), $c->get( CreditRepository::class ), $c->get( ActivityLogger::class ) ); } ); $c->singleton( BillingRunner::class, static function ( Container $c ) { return new BillingRunner( $c->get( RenewalService::class ), $c->get( LateFeeService::class ), $c->get( SuspensionService::class ) ); } ); $c->singleton( CronStatus::class, static function ( Container $c ) { return new CronStatus( $c->get( EmailRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( BillingController::class, static function ( Container $c ) { return new BillingController( $c->get( RenewalService::class ), $c->get( BillingRunner::class ), $c->get( CronStatus::class ), $c->get( Settings::class ) ); } ); // Customer portal. $c->singleton( PortalData::class, static function ( Container $c ) { return new PortalData( $c->get( OrderRepository::class ), $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ), $c->get( InvoiceRepository::class ), $c->get( PaymentRepository::class ), $c->get( NoticeRepository::class ), $c->get( CreditRepository::class ) ); } ); $c->singleton( PortalActions::class, static function ( Container $c ) { return new PortalActions( $c->get( PaymentService::class ), $c->get( CustomerService::class ), $c->get( CustomerRepository::class ), $c->get( PortalData::class ), $c->get( NoticeRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( Portal::class, static function ( Container $c ) { return new Portal( $c->get( PortalData::class ), $c->get( PortalActions::class ), $c->get( Gate::class ), $c->get( CustomerRepository::class ), $c->get( Settings::class ), $c->get( RateLimiter::class ) ); } ); // Reports, search, import and export. $c->singleton( ReportRepository::class, static function () { return new ReportRepository( $GLOBALS['wpdb'] ); } ); $c->singleton( CustomerImportService::class, static function ( Container $c ) { return new CustomerImportService( $c->get( CustomerService::class ) ); } ); $c->singleton( CsvExport::class, static function ( Container $c ) { return new CsvExport( $c->get( CustomerRepository::class ), $c->get( InvoiceRepository::class ), $c->get( PaymentRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( ReportsController::class, static function ( Container $c ) { return new ReportsController( $c->get( ReportRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( SearchController::class, static function ( Container $c ) { return new SearchController( $c->get( CustomerRepository::class ), $c->get( InvoiceRepository::class ), $c->get( OrderRepository::class ), $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ) ); } ); // REST. $c->singleton( SettingsController::class, static function ( Container $c ) { return new SettingsController( $c->get( Settings::class ) ); } ); $c->singleton( CustomersController::class, static function ( Container $c ) { return new CustomersController( $c->get( CustomerService::class ), $c->get( CustomerRepository::class ), $c->get( ContactRepository::class ), $c->get( NoteRepository::class ), $c->get( ActivityRepository::class ), $c->get( Settings::class ), $c->get( CustomerImportService::class ) ); } ); $c->singleton( ProductGroupsController::class, static function ( Container $c ) { return new ProductGroupsController( $c->get( CatalogService::class ), $c->get( GroupRepository::class ) ); } ); $c->singleton( ProductsController::class, static function ( Container $c ) { return new ProductsController( $c->get( CatalogService::class ), $c->get( ProductRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( TaxRatesController::class, static function ( Container $c ) { return new TaxRatesController( $c->get( TaxService::class ), $c->get( TaxRateRepository::class ) ); } ); $c->singleton( CouponsController::class, static function ( Container $c ) { return new CouponsController( $c->get( CouponService::class ), $c->get( CouponRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( OrdersController::class, static function ( Container $c ) { return new OrdersController( $c->get( OrderService::class ), $c->get( FulfilmentService::class ), $c->get( OrderRepository::class ), $c->get( ServiceRepository::class ), $c->get( DomainRepository::class ), $c->get( ActivityRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( ServicesController::class, static function ( Container $c ) { return new ServicesController( $c->get( ServiceService::class ), $c->get( ServiceRepository::class ), $c->get( ImportService::class ), $c->get( Settings::class ), $c->get( PlanChangeService::class ) ); } ); $c->singleton( DomainsController::class, static function ( Container $c ) { return new DomainsController( $c->get( DomainService::class ), $c->get( DomainRepository::class ), $c->get( ImportService::class ) ); } ); $c->singleton( InvoicesController::class, static function ( Container $c ) { return new InvoicesController( $c->get( InvoiceService::class ), $c->get( InvoiceRepository::class ), $c->get( InvoicePresenter::class ) ); } ); $c->singleton( PaymentsController::class, static function ( Container $c ) { return new PaymentsController( $c->get( PaymentService::class ), $c->get( PaymentRepository::class ), $c->get( InvoiceRepository::class ), $c->get( InvoicePresenter::class ) ); } ); $c->singleton( CreditsController::class, static function ( Container $c ) { return new CreditsController( $c->get( CreditService::class ), $c->get( CreditRepository::class ), $c->get( CustomerRepository::class ), $c->get( Settings::class ) ); } ); $c->singleton( Router::class, static function ( Container $c ) { return new Router( $c, array( SettingsController::class, CustomersController::class, ProductGroupsController::class, ProductsController::class, TaxRatesController::class, CouponsController::class, OrdersController::class, ServicesController::class, DomainsController::class, InvoicesController::class, PaymentsController::class, CreditsController::class, EmailTemplatesController::class, EmailsController::class, ReminderRulesController::class, NoticesController::class, BillingController::class, ReportsController::class, SearchController::class, ) ); } ); // Admin. $c->singleton( Assets::class, static function ( Container $c ) { return new Assets( $c->get( I18n::class ), $c->get( Settings::class ) ); } ); $c->singleton( AppShell::class, static function () { return new AppShell(); } ); $c->singleton( Menu::class, static function ( Container $c ) { return new Menu( $c->get( AppShell::class ) ); } ); } /** * Service ids that need to hook into WordPress. * * @return string[] */ private function hookable_services(): array { return array( Upgrader::class, LoginGuard::class, CustomerPrivacy::class, Registration::class, ProductsShortcode::class, OrderForm::class, InvoiceDocument::class, QueueRunner::class, EmailEvents::class, ReminderRunner::class, BillingRunner::class, CronStatus::class, Portal::class, CsvExport::class, Router::class, Assets::class, Menu::class, ); } /** * Prevents cloning. */ private function __clone() {} /** * Prevents unserializing. * * @throws LogicException Always. */ public function __wakeup() { throw new LogicException( 'Cannot unserialize a singleton.' ); } }