Files
2meet-data-optimizer/includes/engine/class-tmdo-type-caster.php
T
wpdev d36bb954d1 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
2026-07-31 05:06:36 +08:00

166 lines
4.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* TMDO_Type_Caster - 型別轉換器
*
* 負責:
* - PHP → DB 序列化(寫入)
* - DB → PHP 反序列化(讀取)
* - wpdb format string 生成
* - 型別驗證與清理
*
* @package WP_Data_Optimizer
*/
// phpcs:disable Squiz.Commenting,Generic.Commenting,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber,Generic.CodeAnalysis.UnusedFunctionParameter,Generic.CodeAnalysis.EmptyStatement,Squiz.PHP.DisallowMultipleAssignments,Squiz.PHP.DisallowSizeFunctionsInLoops,WordPress.WP.I18n.MissingTranslatorsComment,WordPress.PHP.NoSilencedErrors,WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents,Squiz.PHP.CommentedOutCode,Universal.NamingConventions.NoReservedKeywordParameterNames,WordPress.PHP.YodaConditions,Squiz.Commenting.InlineComment.InvalidEndChar -- PR-1 ported from UAE; cleanup PR scheduled.
defined( 'ABSPATH' ) || exit;
final class TMDO_Type_Caster {
/**
* PHP → DB 轉換(寫入)
*/
public static function to_db( $value, array $field_def ) {
$type = $field_def['type'] ?? 'text';
// null 值處理
if ( $value === null ) {
if ( ! empty( $field_def['required'] ) ) {
return $field_def['default'] ?? '';
}
return null;
}
switch ( $type ) {
case 'integer':
return (int) $value;
case 'decimal':
return (float) $value;
case 'boolean':
return self::to_bool( $value ) ? 1 : 0;
case 'date':
return self::format_date( $value, 'Y-m-d' );
case 'datetime':
case 'timestamp':
return self::format_date( $value, 'Y-m-d H:i:s' );
case 'json':
if ( is_string( $value ) ) {
// 若已是 JSON 字串則直接儲存(驗證後)
$decoded = json_decode( $value, true );
if ( json_last_error() === JSON_ERROR_NONE ) {
return $value;
}
}
return wp_json_encode( $value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
case 'enum':
$options = $field_def['options'] ?? array();
$str = (string) $value;
return ( ! empty( $options ) && in_array( $str, $options, true ) ) ? $str : ( $field_def['default'] ?? '' );
case 'binary':
return $value;
case 'text':
return (string) $value;
case 'textarea':
return (string) $value;
default:
// 未知型別:嘗試序列化(向後相容 WordPress get_metadata 行為)
return maybe_serialize( $value );
}
}
/**
* 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':
case 'text':
case 'textarea':
return (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 );
}
}