resolver = $resolver; $this->location_evaluator = $location_evaluator; $this->features = $features; $this->global_settings = $global_settings; } public function register(): void { // Priority 99: themes sometimes filter the document title themselves // — the user's explicit SEO title must win. add_filter( 'pre_get_document_title', array( $this, 'filter_title' ), 99 ); // Legacy path: themes without `title-tag` support (e.g. Divi in its // default configuration) build through wp_title(), which // never reaches pre_get_document_title — cover it too (same approach // as other SEO plugins: return the complete title). add_filter( 'wp_title', array( $this, 'filter_title' ), 99 ); add_filter( 'wp_robots', array( $this, 'filter_robots' ) ); add_filter( 'get_canonical_url', array( $this, 'filter_canonical' ), 10, 2 ); add_action( 'wp_head', array( $this, 'print_meta_tags' ), 5 ); } public function filter_title( string $title ): string { if ( ! $this->should_handle() || ! $this->features->enabled( 'meta_title' ) ) { return $title; } $post = $this->current_post(); if ( null === $post ) { return $title; } $resolved = $this->resolver->title( $post ); return '' !== $resolved ? $resolved : $title; } /** * @param array<string, bool> $robots * * @return array<string, bool> */ public function filter_robots( array $robots ): array { if ( ! $this->should_handle() || ! $this->features->enabled( 'meta_robots' ) ) { return $robots; } $post = $this->current_post(); if ( null === $post ) { return $robots; } $flags = $this->resolver->robots( $post ); if ( ! $flags['index'] ) { $robots['noindex'] = true; } if ( ! $flags['follow'] ) { $robots['nofollow'] = true; } return $robots; } public function filter_canonical( string $canonical_url, \WP_Post $post ): string { if ( ! $this->should_handle() || ! $this->features->enabled( 'canonical' ) ) { return $canonical_url; } if ( ! in_array( $post->post_type, PostTypes::supported(), true ) ) { return $canonical_url; } if ( ! $this->location_evaluator->applies( $post ) ) { return $canonical_url; } $custom = $this->resolver->canonical( $post ); return '' !== $custom ? $custom : $canonical_url; } public function print_meta_tags(): void { $handle = $this->should_handle(); // Opt-in "danger zone" exception (SettingsTab): even when deferring to // a detected conflicting plugin, OG/Twitter alone can still take over // if the user asked for it AND we have a verified way to suppress // that plugin's own OG/Twitter output (ConflictOverrideRunner, hooked // earlier on `wp`). Title/description/canonical stay deferred either way. $og_override = ! $handle && ConflictOverrideRegistry::is_active( $this->global_settings ); if ( ! $handle && ! $og_override ) { return; } $post = $this->current_post(); if ( null === $post ) { return; } $description = $this->resolver->description( $post ); if ( $handle && '' !== $description && $this->features->enabled( 'meta_description' ) ) { printf( '<meta name="description" content="%s" />' . "\n", esc_attr( $description ) ); } if ( ( $handle || $og_override ) && $this->features->enabled( 'open_graph' ) ) { $this->print_open_graph( $post, $description ); } if ( ( $handle || $og_override ) && $this->features->enabled( 'twitter_cards' ) ) { $this->print_twitter_card( $post, $description ); } } private function print_open_graph( \WP_Post $post, string $description ): void { SocialTagsPrinter::open_graph( is_singular( 'post' ) ? 'article' : 'website', $this->social_title( $post ), $this->resolver->canonical( $post ), $description, $this->resolver->og_image_url( $post ) ); } private function print_twitter_card( \WP_Post $post, string $description ): void { SocialTagsPrinter::twitter_card( $this->resolver->twitter_card( $post ), $this->social_title( $post ), $description, $this->resolver->og_image_url( $post ) ); } private function social_title( \WP_Post $post ): string { $title = $this->resolver->title( $post ); return '' !== $title ? $title : get_the_title( $post ); } private function should_handle(): bool { /** * Filters whether Acez SEO should output its own meta tags at all. * * @param bool $should_handle */ return (bool) apply_filters( 'acez_seo_should_handle_meta', ! SeoPluginDetector::has_conflict() ); } private function current_post(): ?\WP_Post { $post = CurrentSingularPost::get(); if ( null === $post || ! $this->location_evaluator->applies( $post ) ) { return null; } return $post; } }