chore: initial snapshot of 2meet-data-optimizer v0.1.0
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
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
/**
|
||||
* WPDO Anti-EAV Aware Trait
|
||||
*
|
||||
* Sugar layer for partner plugins (e.g. tmos-* family) that need to consume
|
||||
* WPDO's anti-EAV registration & I/O surface from a single place.
|
||||
*
|
||||
* Use it on the plugin main class, then implement `plugin_slug()` and override
|
||||
* any of the three `on_register_*()` hooks. Call `bind_anti_eav_hooks()` once
|
||||
* during boot (typically `plugins_loaded:10+`) to attach all three.
|
||||
*
|
||||
* Internally this just delegates to the existing public WPDO surface
|
||||
* (`TMDO_Schema_Registry`, `TMDO_Custom_Table_Registry`, `TMDO_Entity_Registry`,
|
||||
* `TMDO_API`). It exists to (a) give partner plugins one trait to `use`,
|
||||
* (b) document the anti-EAV contract in code, (c) absorb future API drift.
|
||||
*
|
||||
* @package WP_Data_Optimizer
|
||||
* @since 2.17.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Re-declaration guard. The mu-plugin `wpdo-policy-enforcer.php` previously
|
||||
// shipped a minimal stub of this trait; v2.17.0 promotes the canonical
|
||||
// definition to wp-data-optimizer. The mu-plugin now mirrors this file
|
||||
// verbatim. Either load order (mu-plugin first, or WPDO first) ends with
|
||||
// the same trait body in memory.
|
||||
if ( ! trait_exists( 'TMDO_Anti_EAV_Aware' ) ) {
|
||||
|
||||
trait TMDO_Anti_EAV_Aware {
|
||||
|
||||
/**
|
||||
* Plugin slug used as provider identifier when registering fields/tables.
|
||||
*
|
||||
* Partner plugins SHOULD override this with their canonical slug
|
||||
* (e.g. 'tmos-core', 'tmos-events'). Default returns lowercased class name
|
||||
* for backward compatibility with older partner plugins that didn't define
|
||||
* a slug.
|
||||
*/
|
||||
protected function plugin_slug(): string {
|
||||
return strtolower( static::class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach the three `wpdo_register_*` hooks to the corresponding
|
||||
* `on_register_*` methods. Call once during plugin boot.
|
||||
*
|
||||
* Idempotent — safe to call multiple times because WP de-dupes
|
||||
* identical (action, callback) pairs.
|
||||
*/
|
||||
protected function bind_anti_eav_hooks(): void {
|
||||
add_action( 'wpdo_register_fields', array( $this, 'on_register_fields' ), 10, 1 );
|
||||
add_action( 'wpdo_register_custom_tables', array( $this, 'on_register_custom_tables' ), 10, 1 );
|
||||
add_action( 'wpdo_register_entity_fields', array( $this, 'on_register_entity_fields' ), 10, 0 );
|
||||
}
|
||||
|
||||
// ── Hook handlers (override in subclass) ─────────────────────────────────
|
||||
|
||||
/**
|
||||
* Register hot/warm/cold/archive zone field mappings.
|
||||
*
|
||||
* Override in subclass and call `$this->register_field( $registry, [...] )`
|
||||
* for each post-meta key the plugin manages.
|
||||
*
|
||||
* @param TMDO_Schema_Registry $registry The shared field registry.
|
||||
*/
|
||||
public function on_register_fields( TMDO_Schema_Registry $registry ): void {
|
||||
// Default no-op. Override in subclass.
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom tables owned by this plugin.
|
||||
*
|
||||
* Override in subclass and call `$this->register_custom_table( $r, [...] )`
|
||||
* for each table.
|
||||
*
|
||||
* @param TMDO_Custom_Table_Registry $r The shared custom-table registry.
|
||||
*/
|
||||
public function on_register_custom_tables( TMDO_Custom_Table_Registry $r ): void {
|
||||
// Default no-op. Override in subclass.
|
||||
}
|
||||
|
||||
/**
|
||||
* Register entity field groups (user / term / comment / post metadata).
|
||||
*
|
||||
* Override in subclass and call `$this->register_entity_fields( $type, $group, [...] )`
|
||||
* for each logical field group the plugin contributes.
|
||||
*/
|
||||
public function on_register_entity_fields(): void {
|
||||
// Default no-op. Override in subclass.
|
||||
}
|
||||
|
||||
// ── Sugar wrappers around WPDO public API ────────────────────────────────
|
||||
|
||||
/**
|
||||
* Register a single zone field via TMDO_Schema_Registry.
|
||||
*
|
||||
* @param TMDO_Schema_Registry $registry Provided by the `wpdo_register_fields` hook.
|
||||
* @param array<string,mixed> $field_def Field definition (post_type, meta_key, zone, ...).
|
||||
*/
|
||||
protected function register_field( TMDO_Schema_Registry $registry, array $field_def ): void {
|
||||
$registry->register( $this->plugin_slug(), $field_def );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom table via TMDO_Custom_Table_Registry.
|
||||
*
|
||||
* @param TMDO_Custom_Table_Registry $r Provided by the `wpdo_register_custom_tables` hook.
|
||||
* @param array<string,mixed> $table_def Table definition (table_name, primary_key, expected_columns, indexes, ...).
|
||||
*/
|
||||
protected function register_custom_table( TMDO_Custom_Table_Registry $r, array $table_def ): void {
|
||||
$r->register( $this->plugin_slug(), $table_def );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an entity field group via TMDO_Entity_Registry.
|
||||
*
|
||||
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
|
||||
* @param string $group_name Logical group name (e.g. 'tmos_vendor', 'tmos_audience').
|
||||
* @param array<int,array<string,mixed>> $fields Field definitions.
|
||||
*/
|
||||
protected function register_entity_fields( string $entity_type, string $group_name, array $fields ): bool {
|
||||
if ( ! class_exists( 'TMDO_Entity_Registry' ) ) {
|
||||
return false;
|
||||
}
|
||||
return TMDO_Entity_Registry::register_group( $entity_type, $group_name, $fields );
|
||||
}
|
||||
|
||||
// ── Read/write convenience wrappers ──────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Read an entity field via the TMDO_API facade.
|
||||
*
|
||||
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
|
||||
* @param int $entity_id Entity primary id.
|
||||
* @param string $key Meta key.
|
||||
* @param bool $single Return single value (default true).
|
||||
*/
|
||||
protected function get_field( string $entity_type, int $entity_id, string $key, bool $single = true ): mixed {
|
||||
return TMDO_API::get_entity( $entity_type, $entity_id, $key, $single );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an entity field via the TMDO_API facade.
|
||||
*
|
||||
* @param string $entity_type 'post' | 'user' | 'term' | 'comment'.
|
||||
* @param int $entity_id Entity primary id.
|
||||
* @param string $key Meta key.
|
||||
* @param mixed $value Meta value.
|
||||
*
|
||||
* @return bool|int False on failure, otherwise the meta id (add) or true (update).
|
||||
*/
|
||||
protected function set_field( string $entity_type, int $entity_id, string $key, mixed $value ): bool|int {
|
||||
return TMDO_API::set_entity( $entity_type, $entity_id, $key, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to write events on a specific meta key.
|
||||
*
|
||||
* Convenience wrapper around `add_action('wpdo_after_write', ...)` that
|
||||
* filters callbacks to the plugin's own keys via prefix match.
|
||||
*
|
||||
* @param string $key_prefix Meta-key prefix to react on (e.g. 'tmos_vendor_').
|
||||
* @param callable $callback `function(string $entity_type, int $entity_id, string $key, mixed $value, bool $ok, string $op, mixed $before)`.
|
||||
* @param int $priority WordPress action priority (default 10).
|
||||
*/
|
||||
protected function on_after_write( string $key_prefix, callable $callback, int $priority = 10 ): void {
|
||||
add_action(
|
||||
'wpdo_after_write',
|
||||
static function ( $entity_type, $entity_id, $meta_key, $meta_value, $ok, $op, $before ) use ( $key_prefix, $callback ): void {
|
||||
if ( is_string( $meta_key ) && str_starts_with( $meta_key, $key_prefix ) ) {
|
||||
$callback( $entity_type, $entity_id, $meta_key, $meta_value, $ok, $op, $before );
|
||||
}
|
||||
},
|
||||
$priority,
|
||||
7
|
||||
);
|
||||
}
|
||||
|
||||
// ── Backward-compat (legacy 2meet-* mu-plugin trait surface) ─────────────
|
||||
// The pre-v2.17.0 mu-plugin trait stub exposed two abstract static methods
|
||||
// (`register_wpdo_fields`, `register_custom_tables`). Older partner plugins
|
||||
// (e.g. 2meet-inquiries) implemented those static methods. The promoted
|
||||
// trait keeps the names with non-abstract no-op defaults so existing
|
||||
// classes continue to work without modification.
|
||||
|
||||
/**
|
||||
* Legacy entry point for plugins that registered fields via a static method
|
||||
* before v2.17.0. New partner plugins should override `on_register_fields()`
|
||||
* (instance method) instead.
|
||||
*
|
||||
* @deprecated 2.17.0 Use instance method `on_register_fields()` + `bind_anti_eav_hooks()` instead.
|
||||
*/
|
||||
public static function register_wpdo_fields(): void {
|
||||
// No-op default. Legacy classes overrode this and called the registry directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy entry point for plugins that registered custom tables via a static
|
||||
* method before v2.17.0.
|
||||
*
|
||||
* @deprecated 2.17.0 Use instance method `on_register_custom_tables()` + `bind_anti_eav_hooks()` instead.
|
||||
*/
|
||||
public static function register_custom_tables(): void {
|
||||
// No-op default.
|
||||
}
|
||||
}
|
||||
|
||||
} // end if ( ! trait_exists )
|
||||
Reference in New Issue
Block a user