Files
2meet-data-optimizer/tests/live/suites/serialized.php
T
wpdev 08f9e313e0 fix(2meet-data-optimizer): serialize arrays in text fields instead of storing "Array"
- 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
2026-09-26 18:45:59 +08:00

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' );
}
);