feat(2meet-data-optimizer): warn when HivePress / WooCommerce run without their AddOn

- TMDO_Compatibility::missing_integration_addons() reports active HivePress / WooCommerce whose AddOn bootstrap class is absent
- Surface it as Site Health test wpdo_missing_integration_addons (also on the admin Doctor tab) and an administrator notice (TMDO_Missing_Addons_Notice)
- Verify: MissingIntegrationAddonsTest (5, class stand-ins in separate processes); core unit 651 / integration 449, HP 148, WC 10 OK; read-only check: dev20/21 HivePress+WooCommerce, dev22 HivePress, others clean
- PR: PR-035
This commit is contained in:
2026-09-26 00:36:02 +08:00
parent 3d650eb848
commit c84d2409b7
7 changed files with 246 additions and 31 deletions
+55 -20
View File
@@ -2,7 +2,7 @@
/**
* TMDO_Site_Health — WordPress Site Health integration (v2.2.0 M3).
*
* Registers 9 tests under Tools → Site Health → Status:
* Registers 10 tests under Tools → Site Health → Status:
* 1. wpdo_schema_drift (critical)
* 2. wpdo_error_budget (recommended)
* 3. wpdo_hook_conflicts (recommended)
@@ -12,6 +12,7 @@
* 7. wpdo_missing_snapshot (critical)
* 8. wpdo_entity_group_collisions (recommended)
* 9. wpdo_orphaned_entity_groups (recommended)
* 10. wpdo_missing_integration_addons (recommended)
*
* Each test result is cached for 5 minutes to keep Site Health responsive.
*
@@ -36,15 +37,16 @@ class TMDO_Site_Health {
/** Test name → callable suffix mapping. */
private const TESTS = array(
'wpdo_schema_drift' => 'check_schema_drift',
'wpdo_error_budget' => 'check_error_budget',
'wpdo_hook_conflicts' => 'check_hook_conflicts',
'wpdo_autoload_bloat' => 'check_autoload_bloat',
'wpdo_postmeta_explosion' => 'check_postmeta_explosion',
'wpdo_orphan_zone_rows' => 'check_orphan_zone_rows',
'wpdo_missing_snapshot' => 'check_missing_snapshot',
'wpdo_entity_group_collisions' => 'check_entity_group_collisions',
'wpdo_orphaned_entity_groups' => 'check_orphaned_entity_groups',
'wpdo_schema_drift' => 'check_schema_drift',
'wpdo_error_budget' => 'check_error_budget',
'wpdo_hook_conflicts' => 'check_hook_conflicts',
'wpdo_autoload_bloat' => 'check_autoload_bloat',
'wpdo_postmeta_explosion' => 'check_postmeta_explosion',
'wpdo_orphan_zone_rows' => 'check_orphan_zone_rows',
'wpdo_missing_snapshot' => 'check_missing_snapshot',
'wpdo_entity_group_collisions' => 'check_entity_group_collisions',
'wpdo_orphaned_entity_groups' => 'check_orphaned_entity_groups',
'wpdo_missing_integration_addons' => 'check_missing_integration_addons',
);
/**
@@ -57,7 +59,7 @@ class TMDO_Site_Health {
}
/**
* Register the 9 tests with WP Site Health.
* Register the 10 tests with WP Site Health.
*
* @param array $tests Existing tests.
* @return array
@@ -80,15 +82,16 @@ class TMDO_Site_Health {
*/
private static function label_for( string $key ): string {
$map = array(
'wpdo_schema_drift' => __( 'WPDO schema drift', '2meet-data-optimizer' ),
'wpdo_error_budget' => __( 'WPDO error budget', '2meet-data-optimizer' ),
'wpdo_hook_conflicts' => __( 'WPDO hook conflicts', '2meet-data-optimizer' ),
'wpdo_autoload_bloat' => __( 'WPDO autoload bloat', '2meet-data-optimizer' ),
'wpdo_postmeta_explosion' => __( 'WPDO postmeta explosion', '2meet-data-optimizer' ),
'wpdo_orphan_zone_rows' => __( 'WPDO orphan zone rows', '2meet-data-optimizer' ),
'wpdo_missing_snapshot' => __( 'WPDO missing snapshot', '2meet-data-optimizer' ),
'wpdo_entity_group_collisions' => __( 'WPDO entity group collisions', '2meet-data-optimizer' ),
'wpdo_orphaned_entity_groups' => __( 'WPDO orphaned entity groups', '2meet-data-optimizer' ),
'wpdo_schema_drift' => __( 'WPDO schema drift', '2meet-data-optimizer' ),
'wpdo_error_budget' => __( 'WPDO error budget', '2meet-data-optimizer' ),
'wpdo_hook_conflicts' => __( 'WPDO hook conflicts', '2meet-data-optimizer' ),
'wpdo_autoload_bloat' => __( 'WPDO autoload bloat', '2meet-data-optimizer' ),
'wpdo_postmeta_explosion' => __( 'WPDO postmeta explosion', '2meet-data-optimizer' ),
'wpdo_orphan_zone_rows' => __( 'WPDO orphan zone rows', '2meet-data-optimizer' ),
'wpdo_missing_snapshot' => __( 'WPDO missing snapshot', '2meet-data-optimizer' ),
'wpdo_entity_group_collisions' => __( 'WPDO entity group collisions', '2meet-data-optimizer' ),
'wpdo_orphaned_entity_groups' => __( 'WPDO orphaned entity groups', '2meet-data-optimizer' ),
'wpdo_missing_integration_addons' => __( 'WPDO integrations without their AddOn', '2meet-data-optimizer' ),
);
return $map[ $key ] ?? $key;
}
@@ -511,6 +514,38 @@ class TMDO_Site_Health {
);
}
// ─── Test 10: Integrations without their AddOn ──────────────────────
/**
* Report HivePress / WooCommerce running while their AddOn is inactive.
*
* Not cached: two class_exists() probes.
*
* @return array Site Health result.
*/
public static function check_missing_integration_addons(): array {
$missing = class_exists( 'TMDO_Compatibility' ) ? TMDO_Compatibility::missing_integration_addons() : array();
if ( empty( $missing ) ) {
return self::wrap( 'wpdo_missing_integration_addons', self::pass( __( 'Every detected integration has its AddOn active.', '2meet-data-optimizer' ) ) );
}
$lines = array();
foreach ( $missing as $plugin => $addon ) {
$lines[] = "{$plugin} → {$addon}";
}
return self::wrap(
'wpdo_missing_integration_addons',
self::fail(
__( 'WPDO integrations running without their AddOn', '2meet-data-optimizer' ),
sprintf(
/* translators: %s: "Plugin → AddOn" pairs */
__( 'These plugins are active but their AddOn is not, so their fields are not optimised: %s. Activate the AddOn.', '2meet-data-optimizer' ),
implode( '; ', $lines )
),
'recommended'
)
);
}
/**
* Wrap a raw check result with required Site Health envelope fields.
*