Utils.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. <?php
  2. namespace AlibabaCloud\Tea\Utils;
  3. use AlibabaCloud\Tea\Model;
  4. use GuzzleHttp\Psr7\Stream;
  5. use Psr\Http\Message\StreamInterface;
  6. class Utils
  7. {
  8. private static $defaultUserAgent = '';
  9. /**
  10. * Convert a string(utf8) to bytes.
  11. *
  12. * @param string $string
  13. *
  14. * @return array the return bytes
  15. */
  16. public static function toBytes($string)
  17. {
  18. if (self::is_bytes($string)) {
  19. return $string;
  20. }
  21. $bytes = [];
  22. for ($i = 0; $i < \strlen($string); ++$i) {
  23. $bytes[] = \ord($string[$i]);
  24. }
  25. return $bytes;
  26. }
  27. /**
  28. * Convert a bytes to string(utf8).
  29. *
  30. * @param array $bytes
  31. *
  32. * @return string the return string
  33. */
  34. public static function toString($bytes)
  35. {
  36. if (\is_string($bytes)) {
  37. return $bytes;
  38. }
  39. $str = '';
  40. foreach ($bytes as $ch) {
  41. $str .= \chr($ch);
  42. }
  43. return $str;
  44. }
  45. /**
  46. * Parse it by JSON format.
  47. *
  48. * @param string $jsonString
  49. *
  50. * @return array the parsed result
  51. */
  52. public static function parseJSON($jsonString)
  53. {
  54. return json_decode($jsonString, true);
  55. }
  56. /**
  57. * Read data from a readable stream, and compose it to a bytes.
  58. *
  59. * @param StreamInterface $stream the readable stream
  60. *
  61. * @return array the bytes result
  62. */
  63. public static function readAsBytes($stream)
  64. {
  65. $str = self::readAsString($stream);
  66. return self::toBytes($str);
  67. }
  68. /**
  69. * Read data from a readable stream, and compose it to a string.
  70. *
  71. * @param StreamInterface $stream the readable stream
  72. *
  73. * @return string the string result
  74. */
  75. public static function readAsString($stream)
  76. {
  77. if ($stream->isSeekable()) {
  78. $stream->rewind();
  79. }
  80. return $stream->getContents();
  81. }
  82. /**
  83. * Read data from a readable stream, and parse it by JSON format.
  84. *
  85. * @param StreamInterface $stream the readable stream
  86. *
  87. * @return array the parsed result
  88. */
  89. public static function readAsJSON($stream)
  90. {
  91. return self::parseJSON(self::readAsString($stream));
  92. }
  93. /**
  94. * Generate a nonce string.
  95. *
  96. * @return string the nonce string
  97. */
  98. public static function getNonce()
  99. {
  100. return md5(uniqid() . uniqid(md5(microtime(true)), true));
  101. }
  102. /**
  103. * Get an UTC format string by current date, e.g. 'Thu, 06 Feb 2020 07:32:54 GMT'.
  104. *
  105. * @return string the UTC format string
  106. */
  107. public static function getDateUTCString()
  108. {
  109. return gmdate('D, d M Y H:i:s T');
  110. }
  111. /**
  112. * If not set the real, use default value.
  113. *
  114. * @param string $real
  115. * @param string $default
  116. *
  117. * @return string
  118. */
  119. public static function defaultString($real, $default = '')
  120. {
  121. return null === $real ? $default : $real;
  122. }
  123. /**
  124. * If not set the real, use default value.
  125. *
  126. * @param int $real
  127. * @param int $default
  128. *
  129. * @return int the return number
  130. */
  131. public static function defaultNumber($real, $default = 0)
  132. {
  133. if (null === $real) {
  134. return $default;
  135. }
  136. return (int) $real;
  137. }
  138. /**
  139. * Format a map to form string, like a=a%20b%20c.
  140. *
  141. * @param array|object $query
  142. *
  143. * @return string the form string
  144. */
  145. public static function toFormString($query)
  146. {
  147. if (null === $query) {
  148. return '';
  149. }
  150. if (\is_object($query)) {
  151. $query = json_decode(self::toJSONString($query), true);
  152. }
  153. return str_replace('+', '%20', http_build_query($query));
  154. }
  155. /**
  156. * If not set the real, use default value.
  157. *
  158. * @param array|Model $object
  159. *
  160. * @return string the return string
  161. */
  162. public static function toJSONString($object)
  163. {
  164. if (is_string($object)) {
  165. return $object;
  166. }
  167. if ($object instanceof Model) {
  168. $object = $object->toMap();
  169. }
  170. return json_encode($object, JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES);
  171. }
  172. /**
  173. * Check the string is empty?
  174. *
  175. * @param string $val
  176. *
  177. * @return bool if string is null or zero length, return true
  178. *
  179. * @deprecated
  180. */
  181. public static function _empty($val)
  182. {
  183. return empty($val);
  184. }
  185. /**
  186. * Check the string is empty?
  187. *
  188. * @param string $val
  189. *
  190. * @return bool if string is null or zero length, return true
  191. *
  192. * @deprecated
  193. */
  194. public static function emptyWithSuffix($val)
  195. {
  196. return empty($val);
  197. }
  198. /**
  199. * Check the string is empty?
  200. *
  201. * @param string $val
  202. *
  203. * @return bool if string is null or zero length, return true
  204. */
  205. public static function empty_($val)
  206. {
  207. return empty($val);
  208. }
  209. /**
  210. * Check one string equals another one?
  211. *
  212. * @param int $left
  213. * @param int $right
  214. *
  215. * @return bool if equals, return true
  216. */
  217. public static function equalString($left, $right)
  218. {
  219. return $left === $right;
  220. }
  221. /**
  222. * Check one number equals another one?
  223. *
  224. * @param int $left
  225. * @param int $right
  226. *
  227. * @return bool if equals, return true
  228. */
  229. public static function equalNumber($left, $right)
  230. {
  231. return $left === $right;
  232. }
  233. /**
  234. * Check one value is unset.
  235. *
  236. * @param mixed $value
  237. *
  238. * @return bool if unset, return true
  239. */
  240. public static function isUnset(&$value = null)
  241. {
  242. return !isset($value) || null === $value;
  243. }
  244. /**
  245. * Stringify the value of map.
  246. *
  247. * @param array $map
  248. *
  249. * @return array the new stringified map
  250. */
  251. public static function stringifyMapValue($map)
  252. {
  253. if (null === $map) {
  254. return [];
  255. }
  256. foreach ($map as &$node) {
  257. if (is_numeric($node)) {
  258. $node = (string) $node;
  259. } elseif (null === $node) {
  260. $node = '';
  261. } elseif (\is_bool($node)) {
  262. $node = true === $node ? 'true' : 'false';
  263. } elseif (\is_object($node)) {
  264. $node = json_decode(json_encode($node), true);
  265. }
  266. }
  267. return $map;
  268. }
  269. /**
  270. * Anyify the value of map.
  271. *
  272. * @param array $m
  273. *
  274. * @return array the new anyfied map
  275. */
  276. public static function anyifyMapValue($m)
  277. {
  278. return $m;
  279. }
  280. /**
  281. * Assert a value, if it is a boolean, return it, otherwise throws.
  282. *
  283. * @param mixed $value
  284. *
  285. * @return bool the boolean value
  286. */
  287. public static function assertAsBoolean($value)
  288. {
  289. if (\is_bool($value)) {
  290. return $value;
  291. }
  292. throw new \InvalidArgumentException('It is not a boolean value.');
  293. }
  294. /**
  295. * Assert a value, if it is a string, return it, otherwise throws.
  296. *
  297. * @param mixed $value
  298. *
  299. * @return string the string value
  300. */
  301. public static function assertAsString($value)
  302. {
  303. if (\is_string($value)) {
  304. return $value;
  305. }
  306. throw new \InvalidArgumentException('It is not a string value.');
  307. }
  308. private static function is_bytes($value)
  309. {
  310. if (!\is_array($value)) {
  311. return false;
  312. }
  313. $i = 0;
  314. foreach ($value as $k => $ord) {
  315. if ($k !== $i) {
  316. return false;
  317. }
  318. if (!\is_int($ord)) {
  319. return false;
  320. }
  321. if ($ord < 0 || $ord > 255) {
  322. return false;
  323. }
  324. ++$i;
  325. }
  326. return true;
  327. }
  328. /**
  329. * Assert a value, if it is a bytes, return it, otherwise throws.
  330. *
  331. * @param mixed $value
  332. *
  333. * @return bytes the bytes value
  334. */
  335. public static function assertAsBytes($value)
  336. {
  337. if (self::is_bytes($value)) {
  338. return $value;
  339. }
  340. throw new \InvalidArgumentException('It is not a bytes value.');
  341. }
  342. /**
  343. * Assert a value, if it is a number, return it, otherwise throws.
  344. *
  345. * @param mixed $value
  346. *
  347. * @return int the number value
  348. */
  349. public static function assertAsNumber($value)
  350. {
  351. if (\is_numeric($value)) {
  352. return $value;
  353. }
  354. throw new \InvalidArgumentException('It is not a number value.');
  355. }
  356. /**
  357. * Assert a value, if it is a integer, return it, otherwise throws
  358. * @param mixed $value
  359. * @return int the integer value
  360. */
  361. public static function assertAsInteger($value){
  362. if (\is_int($value)) {
  363. return $value;
  364. }
  365. throw new \InvalidArgumentException('It is not a int value.');
  366. }
  367. /**
  368. * Assert a value, if it is a map, return it, otherwise throws.
  369. *
  370. * @param $any
  371. *
  372. * @return array the map value
  373. */
  374. public static function assertAsMap($any)
  375. {
  376. if (\is_array($any)) {
  377. return $any;
  378. }
  379. throw new \InvalidArgumentException('It is not a map value.');
  380. }
  381. public static function assertAsArray($any){
  382. if (\is_array($any)) {
  383. return $any;
  384. }
  385. throw new \InvalidArgumentException('It is not a array value.');
  386. }
  387. /**
  388. * Get user agent, if it userAgent is not null, splice it with defaultUserAgent and return, otherwise return
  389. * defaultUserAgent.
  390. *
  391. * @param string $userAgent
  392. *
  393. * @return string the string value
  394. */
  395. public static function getUserAgent($userAgent = '')
  396. {
  397. if (empty(self::$defaultUserAgent)) {
  398. self::$defaultUserAgent = sprintf('AlibabaCloud (%s; %s) PHP/%s Core/3.1 TeaDSL/1', PHP_OS, \PHP_SAPI, PHP_VERSION);
  399. }
  400. if (!empty($userAgent)) {
  401. return self::$defaultUserAgent . ' ' . $userAgent;
  402. }
  403. return self::$defaultUserAgent;
  404. }
  405. /**
  406. * If the code between 200 and 300, return true, or return false.
  407. *
  408. * @param int $code
  409. *
  410. * @return bool
  411. */
  412. public static function is2xx($code)
  413. {
  414. return $code >= 200 && $code < 300;
  415. }
  416. /**
  417. * If the code between 300 and 400, return true, or return false.
  418. *
  419. * @param int $code
  420. *
  421. * @return bool
  422. */
  423. public static function is3xx($code)
  424. {
  425. return $code >= 300 && $code < 400;
  426. }
  427. /**
  428. * If the code between 400 and 500, return true, or return false.
  429. *
  430. * @param int $code
  431. *
  432. * @return bool
  433. */
  434. public static function is4xx($code)
  435. {
  436. return $code >= 400 && $code < 500;
  437. }
  438. /**
  439. * If the code between 500 and 600, return true, or return false.
  440. *
  441. * @param int $code
  442. *
  443. * @return bool
  444. */
  445. public static function is5xx($code)
  446. {
  447. return $code >= 500 && $code < 600;
  448. }
  449. /**
  450. * Validate model.
  451. *
  452. * @param Model $model
  453. */
  454. public static function validateModel($model)
  455. {
  456. if (null !== $model) {
  457. $model->validate();
  458. }
  459. }
  460. /**
  461. * Model transforms to map[string]any.
  462. *
  463. * @param Model $model
  464. *
  465. * @return array
  466. */
  467. public static function toMap($model)
  468. {
  469. if (null === $model) {
  470. return [];
  471. }
  472. $map = $model->toMap();
  473. $names = $model->getName();
  474. $vars = get_object_vars($model);
  475. foreach ($vars as $k => $v) {
  476. if (false !== strpos($k, 'Shrink') && !isset($names[$k])) {
  477. // A field that has the suffix `Shrink` and is not a Model class property.
  478. $targetKey = ucfirst(substr($k, 0, \strlen($k) - 6));
  479. if (isset($map[$targetKey])) {
  480. // $targetKey exists in $map.
  481. $map[$targetKey] = $v;
  482. }
  483. }
  484. }
  485. return $map;
  486. }
  487. /**
  488. * Suspends the current thread for the specified number of milliseconds.
  489. *
  490. * @param int $millisecond
  491. */
  492. public static function sleep($millisecond)
  493. {
  494. usleep($millisecond * 1000);
  495. }
  496. /**
  497. * Transform input as array.
  498. *
  499. * @param mixed $input
  500. *
  501. * @return array
  502. */
  503. public static function toArray($input)
  504. {
  505. if (\is_array($input)) {
  506. foreach ($input as $k => &$v) {
  507. $v = self::toArray($v);
  508. }
  509. } elseif ($input instanceof Model) {
  510. $input = $input->toMap();
  511. foreach ($input as $k => &$v) {
  512. $v = self::toArray($v);
  513. }
  514. }
  515. return $input;
  516. }
  517. /**
  518. * Assert a value, if it is a readable, return it, otherwise throws.
  519. *
  520. * @param mixed $value
  521. *
  522. * @return Stream the readable value
  523. */
  524. public static function assertAsReadable($value)
  525. {
  526. if (\is_string($value)) {
  527. return new Stream(
  528. fopen('data://text/plain;base64,' .
  529. base64_encode($value), 'r')
  530. );
  531. }
  532. if ($value instanceof Stream) {
  533. return $value;
  534. }
  535. throw new \InvalidArgumentException('It is not a stream value.');
  536. }
  537. }