@@ -72,6 +72,13 @@ static function (string $class): void {
7272 */
7373$ GLOBALS ['wp_options ' ] = $ GLOBALS ['wp_options ' ] ?? [];
7474
75+ /**
76+ * In-memory transient store used by WordPress transient shims.
77+ *
78+ * @var array<string, mixed>
79+ */
80+ $ GLOBALS ['wp_transients ' ] = $ GLOBALS ['wp_transients ' ] ?? [];
81+
7582/**
7683 * In-memory cache store used by the WordPress cache shims.
7784 *
@@ -619,11 +626,11 @@ public function get_var(string $query): ?int
619626 /**
620627 * Stubbed getter for a row result.
621628 *
622- * @param string $query SQL string.
623- * @param int $output Output type (unused).
629+ * @param string $query SQL string.
630+ * @param string| int $output Output type (unused).
624631 * @return array<string, mixed>|null Null to indicate no results.
625632 */
626- public function get_row (string $ query , int $ output = ARRAY_A ): ?array
633+ public function get_row (string $ query , string | int $ output = ARRAY_A ): ?array
627634 {
628635 unset($ output );
629636 $ this ->queries [] = ['query ' => $ query ];
@@ -968,3 +975,357 @@ function deactivate_plugins(string|array $plugins): void
968975 $ GLOBALS ['deactivated_plugins ' ][] = $ plugins ;
969976 }
970977}
978+
979+ // ---------------------------------------------------------------------------
980+ // WordPress constants
981+ // ---------------------------------------------------------------------------
982+
983+ if (! defined ('ARRAY_A ' )) {
984+ /**
985+ * Flag requesting an associative-array result from wpdb::get_row().
986+ */
987+ define ('ARRAY_A ' , 'ARRAY_A ' );
988+ }
989+
990+ // ---------------------------------------------------------------------------
991+ // WordPress class stubs
992+ // ---------------------------------------------------------------------------
993+
994+ if (! class_exists ('WP_Error ' )) {
995+ /**
996+ * Minimal stand-in for WordPress' WP_Error class.
997+ */
998+ class WP_Error
999+ {
1000+ /**
1001+ * Machine-readable error code.
1002+ *
1003+ * @var string
1004+ */
1005+ private string $ code ;
1006+
1007+ /**
1008+ * Human-readable error message.
1009+ *
1010+ * @var string
1011+ */
1012+ private string $ message ;
1013+
1014+ /**
1015+ * Optional structured error data.
1016+ *
1017+ * @var mixed
1018+ */
1019+ private mixed $ data ;
1020+
1021+ /**
1022+ * @param string $code Machine-readable error code.
1023+ * @param string $message Human-readable message.
1024+ * @param mixed $data Optional extra data.
1025+ */
1026+ public function __construct (string $ code = '' , string $ message = '' , mixed $ data = '' )
1027+ {
1028+ $ this ->code = $ code ;
1029+ $ this ->message = $ message ;
1030+ $ this ->data = $ data ;
1031+ }
1032+
1033+ /** @return string */
1034+ public function get_error_code (): string
1035+ {
1036+ return $ this ->code ;
1037+ }
1038+
1039+ /** @return string */
1040+ public function get_error_message (): string
1041+ {
1042+ return $ this ->message ;
1043+ }
1044+
1045+ /** @return mixed */
1046+ public function get_error_data (): mixed
1047+ {
1048+ return $ this ->data ;
1049+ }
1050+ }
1051+ }
1052+
1053+ if (! class_exists ('WP_REST_Request ' )) {
1054+ /**
1055+ * Minimal stand-in for WordPress' WP_REST_Request class.
1056+ */
1057+ class WP_REST_Request
1058+ {
1059+ /**
1060+ * Decoded JSON body parameters.
1061+ *
1062+ * @var array<string, mixed>
1063+ */
1064+ private array $ json_params = [];
1065+
1066+ /**
1067+ * Normalised request headers (lowercase keys).
1068+ *
1069+ * @var array<string, string>
1070+ */
1071+ private array $ headers = [];
1072+
1073+ /**
1074+ * Raw request body.
1075+ *
1076+ * @var string
1077+ */
1078+ private string $ body = '' ;
1079+
1080+ /**
1081+ * @param array<string, mixed> $params Decoded JSON parameters.
1082+ * @return void
1083+ */
1084+ public function set_json_params (array $ params ): void
1085+ {
1086+ $ this ->json_params = $ params ;
1087+ }
1088+
1089+ /**
1090+ * @return array<string, mixed>
1091+ */
1092+ public function get_json_params (): array
1093+ {
1094+ return $ this ->json_params ;
1095+ }
1096+
1097+ /**
1098+ * @param string $key Header name (case-insensitive).
1099+ * @param string $value Header value.
1100+ * @return void
1101+ */
1102+ public function set_header (string $ key , string $ value ): void
1103+ {
1104+ $ this ->headers [strtolower ($ key )] = $ value ;
1105+ }
1106+
1107+ /**
1108+ * @param string $key Header name (case-insensitive).
1109+ * @return string|null Header value or null when absent.
1110+ */
1111+ public function get_header (string $ key ): ?string
1112+ {
1113+ return $ this ->headers [strtolower ($ key )] ?? null ;
1114+ }
1115+
1116+ /**
1117+ * @param string $body Raw request body.
1118+ * @return void
1119+ */
1120+ public function set_body (string $ body ): void
1121+ {
1122+ $ this ->body = $ body ;
1123+ }
1124+
1125+ /** @return string */
1126+ public function get_body (): string
1127+ {
1128+ return $ this ->body ;
1129+ }
1130+ }
1131+ }
1132+
1133+ if (! class_exists ('WP_REST_Response ' )) {
1134+ /**
1135+ * Minimal stand-in for WordPress' WP_REST_Response class.
1136+ */
1137+ class WP_REST_Response
1138+ {
1139+ /**
1140+ * Response payload.
1141+ *
1142+ * @var mixed
1143+ */
1144+ private mixed $ data ;
1145+
1146+ /**
1147+ * HTTP status code.
1148+ *
1149+ * @var int
1150+ */
1151+ private int $ status ;
1152+
1153+ /**
1154+ * @param mixed $data Response payload.
1155+ * @param int $status HTTP status code.
1156+ */
1157+ public function __construct (mixed $ data = null , int $ status = 200 )
1158+ {
1159+ $ this ->data = $ data ;
1160+ $ this ->status = $ status ;
1161+ }
1162+
1163+ /** @return mixed */
1164+ public function get_data (): mixed
1165+ {
1166+ return $ this ->data ;
1167+ }
1168+
1169+ /** @return int */
1170+ public function get_status (): int
1171+ {
1172+ return $ this ->status ;
1173+ }
1174+ }
1175+ }
1176+
1177+ // ---------------------------------------------------------------------------
1178+ // Additional WordPress function stubs
1179+ // ---------------------------------------------------------------------------
1180+
1181+ if (! function_exists ('is_wp_error ' )) {
1182+ /**
1183+ * Determine whether the supplied value is a WP_Error instance.
1184+ *
1185+ * @param mixed $thing Value to inspect.
1186+ * @return bool True when the value is a WP_Error.
1187+ */
1188+ function is_wp_error (mixed $ thing ): bool
1189+ {
1190+ return $ thing instanceof WP_Error;
1191+ }
1192+ }
1193+
1194+ if (! function_exists ('wp_verify_nonce ' )) {
1195+ /**
1196+ * Verify a nonce value.
1197+ * In tests the only accepted value is the literal string 'valid_nonce'.
1198+ *
1199+ * @param string|null $nonce Nonce to verify.
1200+ * @param string $action Nonce action (unused in stub).
1201+ * @return bool True when the nonce is the expected test value.
1202+ */
1203+ function wp_verify_nonce (?string $ nonce , string $ action = '' ): bool
1204+ {
1205+ unset($ action );
1206+ return $ nonce === 'valid_nonce ' ;
1207+ }
1208+ }
1209+
1210+ if (! function_exists ('wp_unslash ' )) {
1211+ /**
1212+ * Strip slashes from a string or array mirroring WordPress' helper.
1213+ *
1214+ * @param mixed $value String or array to unslash.
1215+ * @return mixed Unslashed value.
1216+ */
1217+ function wp_unslash (mixed $ value ): mixed
1218+ {
1219+ if (is_string ($ value )) {
1220+ return stripslashes ($ value );
1221+ }
1222+
1223+ if (is_array ($ value )) {
1224+ return array_map ('wp_unslash ' , $ value );
1225+ }
1226+
1227+ return $ value ;
1228+ }
1229+ }
1230+
1231+ if (! function_exists ('get_locale ' )) {
1232+ /**
1233+ * Return the current WordPress locale.
1234+ * Always returns 'en_US' in the test environment.
1235+ *
1236+ * @return string Locale string.
1237+ */
1238+ function get_locale (): string
1239+ {
1240+ return 'en_US ' ;
1241+ }
1242+ }
1243+
1244+ if (! function_exists ('get_transient ' )) {
1245+ /**
1246+ * Retrieve a transient value from the in-memory store.
1247+ *
1248+ * @param string $transient Transient name.
1249+ * @return mixed Stored value or false when absent.
1250+ */
1251+ function get_transient (string $ transient ): mixed
1252+ {
1253+ return $ GLOBALS ['wp_transients ' ][$ transient ] ?? false ;
1254+ }
1255+ }
1256+
1257+ if (! function_exists ('set_transient ' )) {
1258+ /**
1259+ * Store a transient value in the in-memory store.
1260+ *
1261+ * @param string $transient Transient name.
1262+ * @param mixed $value Value to store.
1263+ * @param int $expiration Ignored in the stub.
1264+ * @return bool Always true.
1265+ */
1266+ function set_transient (string $ transient , mixed $ value , int $ expiration = 0 ): bool
1267+ {
1268+ unset($ expiration );
1269+ $ GLOBALS ['wp_transients ' ][$ transient ] = $ value ;
1270+ return true ;
1271+ }
1272+ }
1273+
1274+ if (! function_exists ('wp_get_schedules ' )) {
1275+ /**
1276+ * Return the standard WordPress cron schedule definitions.
1277+ *
1278+ * @return array<string, array{interval: int, display: string}>
1279+ */
1280+ function wp_get_schedules (): array
1281+ {
1282+ return [
1283+ 'hourly ' => ['interval ' => 3600 , 'display ' => 'Once Hourly ' ],
1284+ 'twicedaily ' => ['interval ' => 43200 , 'display ' => 'Twice Daily ' ],
1285+ 'daily ' => ['interval ' => 86400 , 'display ' => 'Once Daily ' ],
1286+ 'weekly ' => ['interval ' => 604800 , 'display ' => 'Once Weekly ' ],
1287+ ];
1288+ }
1289+ }
1290+
1291+ if (! function_exists ('is_ssl ' )) {
1292+ /**
1293+ * Determine whether the current request uses HTTPS.
1294+ * Always returns false in the test environment.
1295+ *
1296+ * @return bool False.
1297+ */
1298+ function is_ssl (): bool
1299+ {
1300+ return false ;
1301+ }
1302+ }
1303+
1304+ if (! function_exists ('esc_url_raw ' )) {
1305+ /**
1306+ * Sanitise a URL for database storage (no HTML encoding).
1307+ *
1308+ * @param string $url Raw URL.
1309+ * @return string Sanitised URL.
1310+ */
1311+ function esc_url_raw (string $ url ): string
1312+ {
1313+ return filter_var ($ url , FILTER_SANITIZE_URL ) ?: '' ;
1314+ }
1315+ }
1316+
1317+ if (! function_exists ('__ ' )) {
1318+ /**
1319+ * Translate a string.
1320+ * Returns the original text unchanged in the test environment.
1321+ *
1322+ * @param string $text Text to translate.
1323+ * @param string $domain Text domain (unused in stub).
1324+ * @return string Original text.
1325+ */
1326+ function __ (string $ text , string $ domain = '' ): string
1327+ {
1328+ unset($ domain );
1329+ return $ text ;
1330+ }
1331+ }
0 commit comments