*/ public static function detect(): array { $found = array(); // ── Yoast SEO / Yoast SEO Premium ──────────────────────────────── if ( defined( 'WPSEO_VERSION' ) || class_exists( 'WPSEO_Frontend' ) ) { $conflicts = array( 'article', 'breadcrumb', 'organization', 'author' ); // Yoast emits FAQ schema too if its FAQ block is used. if ( class_exists( 'WPSEO_Schema_FAQ_Section' ) ) { $conflicts[] = 'faq'; } $found['yoast'] = array( 'name' => 'Yoast SEO', 'conflicts' => $conflicts, 'doc_url' => 'https://yoast.com/features/schema/', ); } // ── Rank Math ───────────────────────────────────────────────────── if ( defined( 'RANK_MATH_VERSION' ) || class_exists( 'RankMath' ) ) { $found['rankmath'] = array( 'name' => 'Rank Math', 'conflicts' => array( 'article', 'breadcrumb', 'organization', 'author', 'faq', 'howto' ), 'doc_url' => 'https://rankmath.com/kb/schema-markup/', ); } // ── All in One SEO ──────────────────────────────────────────────── if ( defined( 'AIOSEO_VERSION' ) || class_exists( 'AIOSEO\Plugin\AIOSEO' ) ) { $found['aioseo'] = array( 'name' => 'All in One SEO', 'conflicts' => array( 'article', 'breadcrumb', 'organization', 'author', 'faq' ), 'doc_url' => 'https://aioseo.com/docs/schema-markup/', ); } // ── SEOPress ────────────────────────────────────────────────────── if ( defined( 'SEOPRESS_VERSION' ) || function_exists( 'seopress_activation' ) ) { $found['seopress'] = array( 'name' => 'SEOPress', 'conflicts' => array( 'article', 'breadcrumb', 'organization' ), 'doc_url' => 'https://www.seopress.org/support/guides/schema-markup/', ); } // ── The SEO Framework ───────────────────────────────────────────── if ( function_exists( 'the_seo_framework' ) ) { $found['tsf'] = array( 'name' => 'The SEO Framework', 'conflicts' => array( 'article', 'breadcrumb', 'organization', 'author' ), 'doc_url' => 'https://theseoframework.com/?p=2582', ); } return $found; } /** * Return a flat list of schema setting keys that are conflicted by * any currently-active SEO plugin. * * @return string[] e.g. ['article', 'breadcrumb', 'organization'] */ public static function conflicted_keys(): array { $keys = array(); foreach ( self::detect() as $plugin ) { $keys = array_merge( $keys, $plugin['conflicts'] ); } return array_values( array_unique( $keys ) ); } /** * Whether AEOmatic — AI based Answer Engine Optimization currently has any conflicting schema types enabled. */ public static function has_active_conflicts(): bool { $settings = AEOMATIC_Settings::get( 'schema' ); $conflicts = self::conflicted_keys(); foreach ( $conflicts as $key ) { if ( ! empty( $settings[ $key ] ) ) { return true; } } return false; } /** * Show the conflict notice in the admin — only on AEOmatic — AI based Answer Engine Optimization pages, * and only if not already dismissed. */ public function maybe_show_notice(): void { // Only on our admin pages. Reading $_GET['page'] for routing display only — no form processing, no nonce needed. // phpcs:ignore WordPress.Security.NonceVerification.Recommended $aeomatic_current_page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; if ( false === strpos( $aeomatic_current_page, AEOMATIC_Admin::MENU_SLUG ) ) { return; } if ( get_option( self::NOTICE_DISMISSED_KEY ) ) { return; } $plugins = self::detect(); if ( empty( $plugins ) || ! self::has_active_conflicts() ) { return; } $names = implode( ' and ', array_column( $plugins, 'name' ) ); $fix_url = wp_nonce_url( admin_url( 'admin-post.php?action=aeomatic_fix_conflicts' ), 'aeomatic_fix_conflicts' ); $dismiss_url = wp_nonce_url( admin_url( 'admin-post.php?action=aeomatic_fix_conflicts&dismiss=1' ), 'aeomatic_fix_conflicts' ); $conflicted = self::conflicted_keys(); $labels = array( 'article' => 'Article', 'breadcrumb' => 'Breadcrumb', 'organization' => 'Organization', 'author' => 'Author', 'faq' => 'FAQ', 'howto' => 'HowTo', ); $conflict_labels = array_filter( array_map( static fn( $k ) => $labels[ $k ] ?? null, $conflicted ) ); ?>
✓ ' . esc_html__( 'No conflicting SEO plugins detected.', 'aeomatic' ) . ''; } $names = array_column( $plugins, 'name' ); if ( self::has_active_conflicts() ) { $fix_url = wp_nonce_url( admin_url( 'admin-post.php?action=aeomatic_fix_conflicts' ), 'aeomatic_fix_conflicts' ); // translators: %s: comma-separated list of detected SEO plugin names. $aeomatic_conflict_msg = esc_html__( '%s detected — some schema types overlap.', 'aeomatic' ); return sprintf( '⚠ ' . $aeomatic_conflict_msg . ' %s', esc_html( implode( ', ', $names ) ), esc_url( $fix_url ), esc_html__( 'Fix conflicts', 'aeomatic' ) ); } // translators: %s: comma-separated list of detected SEO plugin names. $aeomatic_resolved_msg = esc_html__( '%s detected — conflicts already resolved.', 'aeomatic' ); return sprintf( '✓ ' . $aeomatic_resolved_msg . '', esc_html( implode( ', ', $names ) ) ); } }