$field_def Field definition. * @return string|null */ private static function fit_text( string $value, array $field_def ): ?string { $length = mb_strlen( $value ); if ( $length <= self::TEXT_MAX_CHARS ) { return $value; } TMDO_Logger::warning( 'text_overflow', array( 'group' => $field_def['group'] ?? '', 'key' => $field_def['key'] ?? '', 'length' => $length, ) ); return null; } /** * DB → PHP 轉換(讀取) */ public static function from_db( $value, array $field_def ) { $type = $field_def['type'] ?? 'text'; if ( $value === null ) { return null; } switch ( $type ) { case 'integer': return (int) $value; case 'decimal': return (float) $value; case 'boolean': return (bool) (int) $value; case 'date': case 'datetime': case 'timestamp': return (string) $value; case 'json': $decoded = json_decode( (string) $value, true ); return ( json_last_error() === JSON_ERROR_NONE ) ? $decoded : $value; case 'enum': return (string) $value; case 'text': case 'textarea': // Arrays were stored serialized (to_db); plain strings pass through. return TMDO_Safe_Unserialize::run( (string) $value ); default: // v2.13.3: object-injection-safe unserialize (fixes L-DESER-1). return TMDO_Safe_Unserialize::run( $value ); } } /** * wpdb format 字串(%s / %d / %f) */ public static function get_wpdb_format( string $type ): string { return match ( $type ) { 'integer', 'boolean' => '%d', 'decimal' => '%f', default => '%s', }; } // ───────────────────────────────────────────────────────── // 工具方法 // ───────────────────────────────────────────────────────── private static function to_bool( $value ): bool { if ( is_bool( $value ) ) { return $value; } if ( is_numeric( $value ) ) { return (int) $value !== 0; } $str = strtolower( trim( (string) $value ) ); return in_array( $str, array( 'true', 'yes', 'y', '1', 'on' ), true ); } private static function format_date( $value, string $format ): ?string { if ( $value === '' || $value === null ) { return null; } // 接受 Unix timestamp if ( is_numeric( $value ) ) { return gmdate( $format, (int) $value ); } $ts = strtotime( (string) $value ); if ( $ts === false ) { return null; } return gmdate( $format, $ts ); } }