register_services(); self::$instance->register_hooks(); } return self::$instance; } /** * The booted plugin. */ public static function instance(): self { return self::boot(); } /** * Service container. */ public function container(): Container { return $this->container; } /** * Plugin version. */ public function version(): string { return (string) $this->container->get( 'plugin.version' ); } /** * Constructor. * * @param Container $container Service container. */ private function __construct( Container $container ) { $this->container = $container; } /** * Register the core services. Later milestones (settings, install, admin, ...) add theirs here. */ private function register_services(): void { $this->container->set( 'plugin.version', static fn (): string => CONSENTFOLD_VERSION ); $this->container->set( 'plugin.file', static fn (): string => CONSENTFOLD_FILE ); $this->container->set( 'plugin.dir', static fn (): string => CONSENTFOLD_DIR ); $this->container->set( 'plugin.url', static fn (): string => CONSENTFOLD_URL ); $this->container->set( 'settings', static fn (): Repository => new Repository() ); $this->container->set( 'upgrader', static fn ( Container $container ): Upgrader => new Upgrader( $container->get( 'settings' ) ) ); $this->container->set( 'activator', static fn ( Container $container ): Activator => new Activator( $container->get( 'upgrader' ), $container->get( 'scanner.cron' ) ) ); $this->container->set( 'admin.capabilities', static fn (): Capabilities => new Capabilities() ); $this->container->set( 'admin.page', static fn ( Container $container ): Page => new Page( $container->get( 'plugin.dir' ), $container->get( 'plugin.url' ) ) ); $this->container->set( 'admin.menu', static fn ( Container $container ): Menu => new Menu( $container->get( 'admin.page' ) ) ); $this->container->set( 'admin.preferences', static fn (): Preferences => new Preferences() ); $this->container->set( 'admin.blocking_route', static fn ( Container $container ): BlockingRoute => new BlockingRoute( $container->get( 'settings' ), $container->get( 'blocking.registry' ) ) ); $this->container->set( 'admin.banner_route', static fn ( Container $container ): BannerRoute => new BannerRoute( $container->get( 'settings' ), $container->get( 'frontend.config' ), $container->get( 'fonts.hosted' ), $container->get( 'plugin.dir' ), $container->get( 'plugin.url' ), $container->get( 'plugin.version' ) ) ); $this->container->set( 'admin.fonts_route', static fn ( Container $container ): FontsRoute => new FontsRoute( $container->get( 'fonts.catalog' ), $container->get( 'fonts.hosted' ) ) ); $this->container->set( 'fonts.catalog', static fn ( Container $container ): GoogleFonts => new GoogleFonts( $container->get( 'plugin.dir' ) . 'data/google-fonts.json' ) ); $this->container->set( 'fonts.hosted', static fn ( Container $container ): HostedFonts => new HostedFonts( $container->get( 'fonts.catalog' ) ) ); $this->container->set( 'admin.consent_mode_route', static fn ( Container $container ): ConsentModeRoute => new ConsentModeRoute( $container->get( 'settings' ), $container->get( 'consent.api_bridge' ) ) ); $this->container->set( 'admin.log_route', static fn ( Container $container ): LogRoute => new LogRoute( $container->get( 'settings' ), $container->get( 'consent.log' ) ) ); $this->container->set( 'blocking.registry', static fn ( Container $container ): ServiceRegistry => new ServiceRegistry( $container->get( 'settings' ), $container->get( 'plugin.dir' ) . 'data/services.json' ) ); $this->container->set( 'blocking.neutraliser', static fn ( Container $container ): Neutraliser => new Neutraliser( $container->get( 'blocking.registry' ), $container->get( 'settings' ) ) ); $this->container->set( 'blocking.enqueue_rewriter', static fn ( Container $container ): EnqueueRewriter => new EnqueueRewriter( $container->get( 'blocking.neutraliser' ) ) ); $this->container->set( 'blocking.content_rewriter', static fn ( Container $container ): ContentRewriter => new ContentRewriter( $container->get( 'blocking.neutraliser' ) ) ); $this->container->set( 'blocking.ob_rewriter', static fn ( Container $container ): OutputBufferRewriter => new OutputBufferRewriter( $container->get( 'blocking.neutraliser' ) ) ); $this->container->set( 'consent_mode.google', static fn ( Container $container ): GoogleConsentMode => new GoogleConsentMode( $container->get( 'settings' ), $container->get( 'blocking.registry' ), $container->get( 'plugin.dir' ) . 'data/regions.json', static fn (): array => $container->get( 'frontend.config' )->build() ) ); $this->container->set( 'consent_mode.gtm_recipe', static fn ( Container $container ): GtmRecipe => new GtmRecipe( $container->get( 'plugin.dir' ) . 'data/gtm-recipe.json' ) ); $this->container->set( 'consent_mode.verifier', static fn ( Container $container ): Verifier => new Verifier( $container->get( 'plugin.dir' ), $container->get( 'plugin.url' ), $container->get( 'plugin.version' ) ) ); $this->container->set( 'consent.api_bridge', static fn ( Container $container ): ConsentApiBridge => new ConsentApiBridge( $container->get( 'settings' ), plugin_basename( $container->get( 'plugin.file' ) ) ) ); $this->container->set( 'consent.log', static fn (): LogRepository => new LogRepository() ); $this->container->set( 'consent.pruner', static fn ( Container $container ): LogPruner => new LogPruner( $container->get( 'settings' ), $container->get( 'consent.log' ) ) ); $this->container->set( 'scanner.sources', static fn ( Container $container ): Sources => new Sources( $container->get( 'plugin.dir' ) ) ); $this->container->set( 'scanner.inventory', static fn ( Container $container ): Inventory => new Inventory( $container->get( 'blocking.registry' ), $container->get( 'scanner.runtime' ) ) ); $this->container->set( 'scanner.runtime', static fn ( Container $container ): RuntimeCollector => new RuntimeCollector( $container->get( 'settings' ), $container->get( 'blocking.registry' ), $container->get( 'plugin.dir' ) . 'data/common-hosts.json', $container->get( 'plugin.dir' ), $container->get( 'plugin.url' ), $container->get( 'plugin.version' ) ) ); $this->container->set( 'scanner.dump', static fn (): EnqueueDump => new EnqueueDump() ); $this->container->set( 'scanner.static', static fn ( Container $container ): StaticScanner => new StaticScanner( $container->get( 'blocking.registry' ), $container->get( 'settings' ), $container->get( 'scanner.inventory' ), new OptionInspector(), array( $container->get( 'scanner.sources' ), 'units' ), $container->get( 'plugin.dir' ) . 'data/common-hosts.json', array( $container->get( 'scanner.dump' ), 'request' ) ) ); $this->container->set( 'admin.scanner_route', static fn ( Container $container ): ScannerRoute => new ScannerRoute( $container->get( 'settings' ), $container->get( 'scanner.static' ), $container->get( 'scanner.inventory' ) ) ); $this->container->set( 'admin.policy_route', static fn ( Container $container ): PolicyRoute => new PolicyRoute( $container->get( 'settings' ) ) ); $this->container->set( 'importers.service', static fn ( Container $container ): ImportService => new ImportService( $container->get( 'settings' ), new CookieYes( new CookieYesStore() ), new Complianz( new ComplianzStore() ) ) ); $this->container->set( 'admin.import_route', static fn ( Container $container ): ImportRoute => new ImportRoute( $container->get( 'settings' ), $container->get( 'importers.service' ) ) ); $this->container->set( 'admin.setup_route', static fn (): SetupRoute => new SetupRoute() ); $this->container->set( 'admin.health', static fn ( Container $container ): Health => new Health( $container->get( 'settings' ), $container->get( 'consent.api_bridge' ), $container->get( 'plugin.dir' ) ) ); $this->container->set( 'admin.health_route', static fn ( Container $container ): HealthRoute => new HealthRoute( $container->get( 'admin.health' ) ) ); $this->container->set( 'admin.site_health', static fn ( Container $container ): SiteHealth => new SiteHealth( $container->get( 'admin.health' ) ) ); $this->container->set( 'admin.notices', static fn ( Container $container ): Notices => new Notices( $container->get( 'admin.health' ) ) ); $this->container->set( 'admin.free_copy_notice', static fn (): FreeCopyNotice => new FreeCopyNotice( consentfold_fs()->get_slug() . '/' . basename( CONSENTFOLD_FILE ), consentfold_fs()->premium_plugin_basename() ) ); $this->container->set( 'scanner.cron', static fn ( Container $container ): ScanCron => new ScanCron( $container->get( 'scanner.static' ) ) ); $this->container->set( 'privacy.exporter', static fn ( Container $container ): Exporter => new Exporter( $container->get( 'consent.log' ) ) ); $this->container->set( 'privacy.eraser', static fn ( Container $container ): Eraser => new Eraser( $container->get( 'consent.log' ) ) ); $this->container->set( 'cli.commands', static fn ( Container $container ): Commands => new Commands( $container->get( 'consent.log' ), $container->get( 'consent.pruner' ) ) ); $this->container->set( 'cli.scan_commands', static fn ( Container $container ): ScanCommands => new ScanCommands( $container->get( 'scanner.static' ), $container->get( 'scanner.inventory' ) ) ); $this->container->set( 'rest.public_consent', static fn ( Container $container ): PublicConsentController => new PublicConsentController( $container->get( 'settings' ), $container->get( 'consent.log' ), new RateLimiter() ) ); $this->container->set( 'frontend.details', static fn ( Container $container ): ServiceDetails => new ServiceDetails( $container->get( 'settings' ), $container->get( 'blocking.registry' ), $container->get( 'plugin.version' ) ) ); $this->container->set( 'frontend.config', static fn ( Container $container ): ConfigBuilder => new ConfigBuilder( $container->get( 'settings' ), $container->get( 'blocking.registry' ), $container->get( 'frontend.details' ), $container->get( 'consent_mode.google' ), $container->get( 'consent.api_bridge' ), $container->get( 'plugin.version' ) ) ); $this->container->set( 'frontend.settings_link', static fn (): SettingsLink => new SettingsLink() ); $this->container->set( 'frontend.cookie_policy', static fn ( Container $container ): CookiePolicy => new CookiePolicy( $container->get( 'settings' ), $container->get( 'scanner.inventory' ), $container->get( 'blocking.registry' ), $container->get( 'plugin.dir' ), $container->get( 'plugin.url' ) ) ); $this->container->set( 'frontend.settings_link_block', static fn ( Container $container ): SettingsLinkBlock => new SettingsLinkBlock( $container->get( 'plugin.dir' ) ) ); $this->container->set( 'admin.nav_menu', static fn (): NavMenu => new NavMenu() ); $this->container->set( 'i18n.strings', static fn ( Container $container ): Strings => new Strings( $container->get( 'settings' ) ) ); $this->container->set( 'frontend.assets', static fn ( Container $container ): Assets => new Assets( $container->get( 'frontend.config' ), $container->get( 'plugin.dir' ), $container->get( 'plugin.url' ), $container->get( 'plugin.version' ), $container->get( 'fonts.hosted' ) ) ); } /** * Hook the plugin into WordPress. Later milestones register theirs here. */ private function register_hooks(): void { $this->container->get( 'activator' )->register( CONSENTFOLD_FILE ); // Picks up schema changes shipped by a plugin update, which does not trigger activation. add_action( 'plugins_loaded', array( $this->container->get( 'upgrader' ), 'maybe_run' ) ); $this->container->get( 'admin.capabilities' )->register(); // Both only act on admin requests: `admin_menu` and `admin_enqueue_scripts` never fire elsewhere. $this->container->get( 'admin.menu' )->register(); $this->container->get( 'admin.page' )->register(); $this->container->get( 'admin.preferences' )->register(); $this->container->get( 'admin.blocking_route' )->register(); $this->container->get( 'admin.banner_route' )->register(); $this->container->get( 'admin.fonts_route' )->register(); $this->container->get( 'admin.consent_mode_route' )->register(); $this->container->get( 'admin.log_route' )->register(); $this->container->get( 'admin.scanner_route' )->register(); $this->container->get( 'admin.policy_route' )->register(); $this->container->get( 'admin.import_route' )->register(); $this->container->get( 'admin.setup_route' )->register(); $this->container->get( 'admin.health' )->register(); $this->container->get( 'admin.health_route' )->register(); $this->container->get( 'admin.site_health' )->register(); $this->container->get( 'admin.notices' )->register(); $this->container->get( 'admin.free_copy_notice' )->register(); $this->container->get( 'blocking.registry' )->register(); // The rewriters leave admin requests alone; the neutraliser checks. $this->container->get( 'blocking.enqueue_rewriter' )->register(); $this->container->get( 'blocking.content_rewriter' )->register(); $this->container->get( 'blocking.ob_rewriter' )->register(); // Registered before the assets so that, at the same `wp_head` priority, the default comes first. $this->container->get( 'consent_mode.google' )->register(); $this->container->get( 'consent_mode.gtm_recipe' )->register(); $this->container->get( 'consent_mode.verifier' )->register(); $this->container->get( 'consent.api_bridge' )->register(); // The route answers REST requests, which load no front-end hooks. $this->container->get( 'rest.public_consent' )->register(); $this->container->get( 'consent.pruner' )->register(); $this->container->get( 'privacy.exporter' )->register(); $this->container->get( 'privacy.eraser' )->register(); $this->container->get( 'cli.commands' )->register(); $this->container->get( 'cli.scan_commands' )->register(); $this->container->get( 'scanner.cron' )->register(); $this->container->get( 'scanner.inventory' )->register(); // Answers the scan's own request for the registered scripts; front-end requests only. $this->container->get( 'scanner.dump' )->register(); // The route answers REST requests, which load no front-end hooks; the script is for managers' front-end visits. $this->container->get( 'scanner.runtime' )->register(); // The assets hook `wp_enqueue_scripts` and `wp_head`, which fire on the front end only. $this->container->get( 'frontend.config' )->register(); // The route answers REST requests, which load no front-end hooks. $this->container->get( 'frontend.details' )->register(); $this->container->get( 'frontend.assets' )->register(); $this->container->get( 'frontend.settings_link' )->register(); // Registered on `init`, which also runs for the editor and the REST requests that render the block. $this->container->get( 'frontend.cookie_policy' )->register(); $this->container->get( 'frontend.settings_link_block' )->register(); $this->container->get( 'admin.nav_menu' )->register(); $this->container->get( 'i18n.strings' )->register(); /** * Fires once the plugin has registered its hooks, for add-on code to attach to. * * @param Container $container Service container. */ do_action( 'consentfold_loaded', $this->container ); } }