b4400a68e5
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
170 lines
4.6 KiB
PHP
170 lines
4.6 KiB
PHP
<?php
|
|
/**
|
|
* Memberships adapter — `hivepress-memberships`.
|
|
*
|
|
* Two post-type models:
|
|
*
|
|
* - Membership_Plan (post_type=hp_membership_plan)
|
|
* hot fields: hp_expire_period (int), hp_primary (bool)
|
|
*
|
|
* - Membership (post_type=hp_membership)
|
|
* hot fields: hp_expired_time (unix ts) — checked on every page load
|
|
*
|
|
* Both fields registered to Hot zone so:
|
|
* - `hp_expired_time < NOW()` lookups become indexed range scans
|
|
* (replaces O(N) postmeta scan on each request).
|
|
* - `hp_primary = 1` lookups for "default plan" become O(1).
|
|
*
|
|
* Tables `wp_wpdo_hot_hp_membership_plan` and `wp_wpdo_hot_hp_membership`
|
|
* are created by `TMDO_Schema_Manager` from the registered hot columns.
|
|
*
|
|
* @package WP_Data_Optimizer
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
if ( ! class_exists( 'TMDO_HivePress_Memberships_Adapter' ) ) {
|
|
|
|
/**
|
|
* Memberships addon adapter.
|
|
*/
|
|
final class TMDO_HivePress_Memberships_Adapter implements TMDO_HivePress_Adapter {
|
|
|
|
use TMDO_HivePress_Adapter_Trait;
|
|
|
|
/**
|
|
* Constructor — bind register hooks via inherited trait.
|
|
*/
|
|
public function __construct() {
|
|
$this->bind_anti_eav_hooks();
|
|
}
|
|
|
|
/** Adapter slug (matches wp.org plugin slug). */
|
|
public function plugin_slug(): string {
|
|
return 'hivepress-memberships';
|
|
}
|
|
|
|
/** Class probed for addon presence. */
|
|
public function detection_class(): string {
|
|
return 'HivePress\\Memberships\\Plugin';
|
|
}
|
|
|
|
/** Version constant probed for addon presence. */
|
|
public function detection_const(): string {
|
|
return 'HIVEPRESS_MEMBERSHIPS_VERSION';
|
|
}
|
|
|
|
/** Minimum addon version supported. */
|
|
public function minimum_addon_version(): string {
|
|
return '2.0.0';
|
|
}
|
|
|
|
/**
|
|
* Register hot fields for both post types.
|
|
*
|
|
* @param TMDO_Schema_Registry $registry Schema registry singleton.
|
|
*/
|
|
public function on_register_fields( TMDO_Schema_Registry $registry ): void {
|
|
$registry->register_many(
|
|
$this->plugin_slug(),
|
|
array(
|
|
// Plan fields.
|
|
array(
|
|
'post_type' => 'hp_membership_plan',
|
|
'meta_key' => 'hp_expire_period',
|
|
'zone' => 'hot',
|
|
'data_type' => 'int(11) NOT NULL DEFAULT 0',
|
|
'column' => 'hp_expire_period',
|
|
'indexed' => false,
|
|
),
|
|
array(
|
|
'post_type' => 'hp_membership_plan',
|
|
'meta_key' => 'hp_primary',
|
|
'zone' => 'hot',
|
|
'data_type' => 'tinyint(1) NOT NULL DEFAULT 0',
|
|
'column' => 'hp_primary',
|
|
'indexed' => true,
|
|
),
|
|
// Membership (subscription) field — hottest path: every page load.
|
|
array(
|
|
'post_type' => 'hp_membership',
|
|
'meta_key' => 'hp_expired_time',
|
|
'zone' => 'hot',
|
|
'data_type' => 'bigint(20) UNSIGNED NOT NULL DEFAULT 0',
|
|
'column' => 'hp_expired_time',
|
|
'indexed' => true,
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Doctor probe — verify both hot tables.
|
|
*
|
|
* @return array{ok:bool, message:string, details?:array<string,mixed>}
|
|
*/
|
|
public function doctor_check(): array {
|
|
global $wpdb;
|
|
if ( ! isset( $wpdb ) || ! is_object( $wpdb ) ) {
|
|
return array(
|
|
'ok' => false,
|
|
'message' => 'wpdb global not available',
|
|
);
|
|
}
|
|
$details = array();
|
|
$ok = true;
|
|
foreach ( array( 'hp_membership_plan', 'hp_membership' ) as $pt ) {
|
|
$table = $wpdb->prefix . 'wpdo_hot_' . sanitize_key( $pt );
|
|
try {
|
|
$exists = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) );
|
|
$details[ $pt ]['table'] = $table;
|
|
$details[ $pt ]['exists'] = $exists;
|
|
if ( ! $exists ) {
|
|
$ok = false;
|
|
}
|
|
} catch ( \Throwable $e ) {
|
|
$details[ $pt ]['error'] = $e->getMessage();
|
|
$ok = false;
|
|
}
|
|
}
|
|
return array(
|
|
'ok' => $ok,
|
|
'message' => $ok ? 'hivepress-memberships: hot tables OK' : 'hivepress-memberships: hot tables missing',
|
|
'details' => $details,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 8-D self-score.
|
|
*
|
|
* D1: 1.0 — adapter never calls *_meta()
|
|
* D2: 1.0 — uses wpdb prefix
|
|
* D3: 1.0 — both models have hot tables
|
|
* D4: 1.0 — every field has explicit data_type + indexed flag
|
|
* D5: 1.0 — single-adapter scope
|
|
* D6: 1.0 — zero options/transients
|
|
* D7: 1.0 — only registers fields, no cross-table queries
|
|
* D8: 1.0 — hot column on hp_expired_time = indexed range scan
|
|
*/
|
|
public function suitability_score(): array {
|
|
return $this->compose_score( array() );
|
|
}
|
|
|
|
/**
|
|
* FSM modules this adapter contributes.
|
|
*
|
|
* @return array<int,string>
|
|
*/
|
|
public function migrations(): array {
|
|
return array(
|
|
'hot_hp_membership_plan',
|
|
'hot_hp_membership',
|
|
);
|
|
}
|
|
}
|
|
|
|
} // end if ( ! class_exists )
|