08f9e313e0
- TMDO_Type_Caster: text / textarea values that are arrays or objects are stored with maybe_serialize() (was (string) → the literal "Array", which bridge-restore-native then wrote back over native meta); from_db() unserializes them with TMDO_Safe_Unserialize. text columns are VARCHAR(255): longer values are stored NULL (native keeps them) and logged as text_overflow. - Add `wp tmdo repair-array-literals [--entity] [--confirm]` (TMDO_Array_Literal_Repair): rewrites flat "Array" values from native meta and lists native rows that are "Array" themselves (backup needed). - Verify: TypeCasterSerializeTest 13 OK, ArrayLiteralRepairTest 3 OK; unit 685 OK, integration 483 OK, phpcs (phpcs.xml) 0, stan OK; live `serialized` 3 PASS; dev36 repair dry-run lists the value corrupted by the 2026-09-26 round trip (user #1 community-events-location) - PR: PR-055
60 lines
2.5 KiB
PHP
60 lines
2.5 KiB
PHP
<?php
|
|
/**
|
|
* Suite: array meta values survive the flat tables (no "Array" literal).
|
|
*
|
|
* Bug (dev36, 2026-09-26): admin_prefs `community-events-location` (text) and
|
|
* `wp_persisted_preferences` (textarea) hold arrays; the type caster stored
|
|
* (string) $array = "Array", and bridge-restore-native wrote it back to native.
|
|
*
|
|
* @package WP_Data_Optimizer
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
TMDO_Live::test(
|
|
'dual_write: array written with update_user_meta is stored serialized',
|
|
static function () {
|
|
TMDO_Live_Fixtures::field( 'user', 'wp_persisted_preferences' );
|
|
TMDO_Live_Fixtures::use_modes( array( 'user' => 'dual_write' ) );
|
|
$uid = TMDO_Live_Fixtures::user();
|
|
$prefs = array( 'core' => array( 'welcomeGuide' => false ) );
|
|
$loc = array( 'ip' => '192.0.2.0' );
|
|
|
|
update_user_meta( $uid, 'wp_persisted_preferences', $prefs );
|
|
update_user_meta( $uid, 'community-events-location', $loc );
|
|
|
|
tmdo_live_assert_same( serialize( $prefs ), TMDO_Live_Fixtures::flat( 'user', $uid, 'wp_persisted_preferences' ), 'flat wp_persisted_preferences' );
|
|
tmdo_live_assert_same( serialize( $loc ), TMDO_Live_Fixtures::flat( 'user', $uid, 'community-events-location' ), 'flat community-events-location' );
|
|
}
|
|
);
|
|
|
|
TMDO_Live::test(
|
|
'backfill: native array meta is flattened serialized, not "Array"',
|
|
static function () {
|
|
TMDO_Live_Fixtures::field( 'user', 'community-events-location' );
|
|
TMDO_Live_Fixtures::use_modes( array( 'user' => 'disabled' ) );
|
|
$uid = TMDO_Live_Fixtures::user();
|
|
$loc = array( 'ip' => '198.51.100.0' );
|
|
update_user_meta( $uid, 'community-events-location', $loc );
|
|
tmdo_live_assert_same( array( serialize( $loc ) ), TMDO_Live_Fixtures::native( 'user', $uid, 'community-events-location' ), 'native precondition' );
|
|
|
|
$field = TMDO_Entity_Registry::get_field( 'user', 'community-events-location' );
|
|
TMDO_Entity_Migration_Engine::reset_checkpoint( 'user', $field['group'] );
|
|
TMDO_Entity_Migration_Engine::migrate_group( 'user', $field['group'], array( 'sleep_ms' => 0, 'resume' => false ) );
|
|
|
|
tmdo_live_assert_same( serialize( $loc ), TMDO_Live_Fixtures::flat( 'user', $uid, 'community-events-location' ), 'flat after backfill' );
|
|
}
|
|
);
|
|
|
|
TMDO_Live::test(
|
|
'read path: from_db returns the array, not a serialized string',
|
|
static function () {
|
|
$field = TMDO_Live_Fixtures::field( 'user', 'wp_persisted_preferences' );
|
|
$prefs = array( 'core/edit-post' => array( 'panels' => array( 'a', 'b' ) ) );
|
|
|
|
$stored = TMDO_Type_Caster::to_db( $prefs, $field );
|
|
|
|
tmdo_live_assert_same( $prefs, TMDO_Type_Caster::from_db( $stored, $field ), 'round trip' );
|
|
}
|
|
);
|