require_files(); $this->build_graph(); $this->register_default_sections(); $this->register_extension_sections(); $this->scheduler->register(); } /** * Section files live under `seo/email-report-sections/` (hyphenated) * but the namespace uses underscores — autoloader can't bridge that * mismatch. Explicit require keeps boot order deterministic. */ private function require_files(): void { $base = THINKRANK_PLUGIN_DIR . 'includes/seo/email-report-sections/'; require_once $base . 'interface-email-report-section.php'; require_once $base . 'class-email-report-html.php'; require_once $base . 'class-top-posts-renderer.php'; require_once $base . 'class-key-metrics-section.php'; require_once $base . 'class-position-summary-section.php'; require_once $base . 'class-top-winning-posts-section.php'; require_once $base . 'class-top-losing-posts-section.php'; require_once $base . 'class-top-winning-keywords-section.php'; require_once $base . 'class-top-losing-keywords-section.php'; require_once $base . 'class-site-traffic-section.php'; require_once $base . 'class-ai-search-section.php'; // Defaults config is procedural — load eagerly. require_once THINKRANK_PLUGIN_DIR . 'includes/config/email-report-settings-config.php'; } private function build_graph(): void { $this->config = new Email_Report_Config(); $this->registry = new Email_Report_Section_Registry(); $this->renderer = new Email_Report_Renderer($this->registry); $this->mailer = new Email_Report_Mailer(); $this->data_provider = new Email_Report_Data_Provider(); $this->generator = new Email_Report_Generator( $this->config, $this->renderer, $this->mailer, $this->data_provider ); $this->scheduler = new Email_Report_Scheduler($this->config, $this->generator); } private function register_default_sections(): void { // Registration order is render order: the hero, what grew, what // fell, where things rank, then the optional GA4 and AI cards. $this->registry->register(new Key_Metrics_Section()); $this->registry->register(new Top_Winning_Posts_Section()); $this->registry->register(new Top_Winning_Keywords_Section()); $this->registry->register(new Top_Losing_Posts_Section()); $this->registry->register(new Top_Losing_Keywords_Section()); $this->registry->register(new Position_Summary_Section()); $this->registry->register(new Site_Traffic_Section()); $this->registry->register(new Ai_Search_Section()); } private function register_extension_sections(): void { /** * Pro plugin (or any other plugin) hooks here and calls * $registry->register(new MySection()) * to add or override a section. * * @since 1.9.0 * * @param Email_Report_Section_Registry $registry */ do_action('thinkrank_email_report_register_sections', $this->registry); } // Accessors used by the REST endpoint. public function config(): Email_Report_Config { return $this->config; } public function registry(): Email_Report_Section_Registry { return $this->registry; } public function generator(): Email_Report_Generator { return $this->generator; } public function scheduler(): Email_Report_Scheduler { return $this->scheduler; } public function data_provider(): Email_Report_Data_Provider { return $this->data_provider; } }