/SafeForKids/vendor/webmozart/assert/src/Assert.php

https://gitlab.com/rocs/Streaming-Safe-for-Kids · PHP · 948 lines · 707 code · 103 blank · 138 comment · 84 complexity · c439c21533ef46769bc75ab82466020f MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the webmozart/assert package.
  4. *
  5. * (c) Bernhard Schussek <bschussek@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Webmozart\Assert;
  11. use BadMethodCallException;
  12. use InvalidArgumentException;
  13. use Traversable;
  14. use Exception;
  15. use Throwable;
  16. use Closure;
  17. /**
  18. * Efficient assertions to validate the input/output of your methods.
  19. *
  20. * @method static void nullOrString($value, $message = '')
  21. * @method static void nullOrStringNotEmpty($value, $message = '')
  22. * @method static void nullOrInteger($value, $message = '')
  23. * @method static void nullOrIntegerish($value, $message = '')
  24. * @method static void nullOrFloat($value, $message = '')
  25. * @method static void nullOrNumeric($value, $message = '')
  26. * @method static void nullOrBoolean($value, $message = '')
  27. * @method static void nullOrScalar($value, $message = '')
  28. * @method static void nullOrObject($value, $message = '')
  29. * @method static void nullOrResource($value, $type = null, $message = '')
  30. * @method static void nullOrIsCallable($value, $message = '')
  31. * @method static void nullOrIsArray($value, $message = '')
  32. * @method static void nullOrIsTraversable($value, $message = '')
  33. * @method static void nullOrIsInstanceOf($value, $class, $message = '')
  34. * @method static void nullOrNotInstanceOf($value, $class, $message = '')
  35. * @method static void nullOrIsEmpty($value, $message = '')
  36. * @method static void nullOrNotEmpty($value, $message = '')
  37. * @method static void nullOrTrue($value, $message = '')
  38. * @method static void nullOrFalse($value, $message = '')
  39. * @method static void nullOrEq($value, $value2, $message = '')
  40. * @method static void nullOrNotEq($value,$value2, $message = '')
  41. * @method static void nullOrSame($value, $value2, $message = '')
  42. * @method static void nullOrNotSame($value, $value2, $message = '')
  43. * @method static void nullOrGreaterThan($value, $value2, $message = '')
  44. * @method static void nullOrGreaterThanEq($value, $value2, $message = '')
  45. * @method static void nullOrLessThan($value, $value2, $message = '')
  46. * @method static void nullOrLessThanEq($value, $value2, $message = '')
  47. * @method static void nullOrRange($value, $min, $max, $message = '')
  48. * @method static void nullOrOneOf($value, $values, $message = '')
  49. * @method static void nullOrContains($value, $subString, $message = '')
  50. * @method static void nullOrStartsWith($value, $prefix, $message = '')
  51. * @method static void nullOrStartsWithLetter($value, $message = '')
  52. * @method static void nullOrEndsWith($value, $suffix, $message = '')
  53. * @method static void nullOrRegex($value, $pattern, $message = '')
  54. * @method static void nullOrAlpha($value, $message = '')
  55. * @method static void nullOrDigits($value, $message = '')
  56. * @method static void nullOrAlnum($value, $message = '')
  57. * @method static void nullOrLower($value, $message = '')
  58. * @method static void nullOrUpper($value, $message = '')
  59. * @method static void nullOrLength($value, $length, $message = '')
  60. * @method static void nullOrMinLength($value, $min, $message = '')
  61. * @method static void nullOrMaxLength($value, $max, $message = '')
  62. * @method static void nullOrLengthBetween($value, $min, $max, $message = '')
  63. * @method static void nullOrFileExists($value, $message = '')
  64. * @method static void nullOrFile($value, $message = '')
  65. * @method static void nullOrDirectory($value, $message = '')
  66. * @method static void nullOrReadable($value, $message = '')
  67. * @method static void nullOrWritable($value, $message = '')
  68. * @method static void nullOrClassExists($value, $message = '')
  69. * @method static void nullOrSubclassOf($value, $class, $message = '')
  70. * @method static void nullOrImplementsInterface($value, $interface, $message = '')
  71. * @method static void nullOrPropertyExists($value, $property, $message = '')
  72. * @method static void nullOrPropertyNotExists($value, $property, $message = '')
  73. * @method static void nullOrMethodExists($value, $method, $message = '')
  74. * @method static void nullOrMethodNotExists($value, $method, $message = '')
  75. * @method static void nullOrKeyExists($value, $key, $message = '')
  76. * @method static void nullOrKeyNotExists($value, $key, $message = '')
  77. * @method static void nullOrCount($value, $key, $message = '')
  78. * @method static void nullOrUuid($values, $message = '')
  79. * @method static void allString($values, $message = '')
  80. * @method static void allStringNotEmpty($values, $message = '')
  81. * @method static void allInteger($values, $message = '')
  82. * @method static void allIntegerish($values, $message = '')
  83. * @method static void allFloat($values, $message = '')
  84. * @method static void allNumeric($values, $message = '')
  85. * @method static void allBoolean($values, $message = '')
  86. * @method static void allScalar($values, $message = '')
  87. * @method static void allObject($values, $message = '')
  88. * @method static void allResource($values, $type = null, $message = '')
  89. * @method static void allIsCallable($values, $message = '')
  90. * @method static void allIsArray($values, $message = '')
  91. * @method static void allIsTraversable($values, $message = '')
  92. * @method static void allIsInstanceOf($values, $class, $message = '')
  93. * @method static void allNotInstanceOf($values, $class, $message = '')
  94. * @method static void allNull($values, $message = '')
  95. * @method static void allNotNull($values, $message = '')
  96. * @method static void allIsEmpty($values, $message = '')
  97. * @method static void allNotEmpty($values, $message = '')
  98. * @method static void allTrue($values, $message = '')
  99. * @method static void allFalse($values, $message = '')
  100. * @method static void allEq($values, $value2, $message = '')
  101. * @method static void allNotEq($values,$value2, $message = '')
  102. * @method static void allSame($values, $value2, $message = '')
  103. * @method static void allNotSame($values, $value2, $message = '')
  104. * @method static void allGreaterThan($values, $value2, $message = '')
  105. * @method static void allGreaterThanEq($values, $value2, $message = '')
  106. * @method static void allLessThan($values, $value2, $message = '')
  107. * @method static void allLessThanEq($values, $value2, $message = '')
  108. * @method static void allRange($values, $min, $max, $message = '')
  109. * @method static void allOneOf($values, $values, $message = '')
  110. * @method static void allContains($values, $subString, $message = '')
  111. * @method static void allStartsWith($values, $prefix, $message = '')
  112. * @method static void allStartsWithLetter($values, $message = '')
  113. * @method static void allEndsWith($values, $suffix, $message = '')
  114. * @method static void allRegex($values, $pattern, $message = '')
  115. * @method static void allAlpha($values, $message = '')
  116. * @method static void allDigits($values, $message = '')
  117. * @method static void allAlnum($values, $message = '')
  118. * @method static void allLower($values, $message = '')
  119. * @method static void allUpper($values, $message = '')
  120. * @method static void allLength($values, $length, $message = '')
  121. * @method static void allMinLength($values, $min, $message = '')
  122. * @method static void allMaxLength($values, $max, $message = '')
  123. * @method static void allLengthBetween($values, $min, $max, $message = '')
  124. * @method static void allFileExists($values, $message = '')
  125. * @method static void allFile($values, $message = '')
  126. * @method static void allDirectory($values, $message = '')
  127. * @method static void allReadable($values, $message = '')
  128. * @method static void allWritable($values, $message = '')
  129. * @method static void allClassExists($values, $message = '')
  130. * @method static void allSubclassOf($values, $class, $message = '')
  131. * @method static void allImplementsInterface($values, $interface, $message = '')
  132. * @method static void allPropertyExists($values, $property, $message = '')
  133. * @method static void allPropertyNotExists($values, $property, $message = '')
  134. * @method static void allMethodExists($values, $method, $message = '')
  135. * @method static void allMethodNotExists($values, $method, $message = '')
  136. * @method static void allKeyExists($values, $key, $message = '')
  137. * @method static void allKeyNotExists($values, $key, $message = '')
  138. * @method static void allCount($values, $key, $message = '')
  139. * @method static void allUuid($values, $message = '')
  140. *
  141. * @since 1.0
  142. *
  143. * @author Bernhard Schussek <bschussek@gmail.com>
  144. */
  145. class Assert
  146. {
  147. public static function string($value, $message = '')
  148. {
  149. if (!is_string($value)) {
  150. static::reportInvalidArgument(sprintf(
  151. $message ?: 'Expected a string. Got: %s',
  152. static::typeToString($value)
  153. ));
  154. }
  155. }
  156. public static function stringNotEmpty($value, $message = '')
  157. {
  158. static::string($value, $message);
  159. static::notEmpty($value, $message);
  160. }
  161. public static function integer($value, $message = '')
  162. {
  163. if (!is_int($value)) {
  164. static::reportInvalidArgument(sprintf(
  165. $message ?: 'Expected an integer. Got: %s',
  166. static::typeToString($value)
  167. ));
  168. }
  169. }
  170. public static function integerish($value, $message = '')
  171. {
  172. if (!is_numeric($value) || $value != (int) $value) {
  173. static::reportInvalidArgument(sprintf(
  174. $message ?: 'Expected an integerish value. Got: %s',
  175. static::typeToString($value)
  176. ));
  177. }
  178. }
  179. public static function float($value, $message = '')
  180. {
  181. if (!is_float($value)) {
  182. static::reportInvalidArgument(sprintf(
  183. $message ?: 'Expected a float. Got: %s',
  184. static::typeToString($value)
  185. ));
  186. }
  187. }
  188. public static function numeric($value, $message = '')
  189. {
  190. if (!is_numeric($value)) {
  191. static::reportInvalidArgument(sprintf(
  192. $message ?: 'Expected a numeric. Got: %s',
  193. static::typeToString($value)
  194. ));
  195. }
  196. }
  197. public static function boolean($value, $message = '')
  198. {
  199. if (!is_bool($value)) {
  200. static::reportInvalidArgument(sprintf(
  201. $message ?: 'Expected a boolean. Got: %s',
  202. static::typeToString($value)
  203. ));
  204. }
  205. }
  206. public static function scalar($value, $message = '')
  207. {
  208. if (!is_scalar($value)) {
  209. static::reportInvalidArgument(sprintf(
  210. $message ?: 'Expected a scalar. Got: %s',
  211. static::typeToString($value)
  212. ));
  213. }
  214. }
  215. public static function object($value, $message = '')
  216. {
  217. if (!is_object($value)) {
  218. static::reportInvalidArgument(sprintf(
  219. $message ?: 'Expected an object. Got: %s',
  220. static::typeToString($value)
  221. ));
  222. }
  223. }
  224. public static function resource($value, $type = null, $message = '')
  225. {
  226. if (!is_resource($value)) {
  227. static::reportInvalidArgument(sprintf(
  228. $message ?: 'Expected a resource. Got: %s',
  229. static::typeToString($value)
  230. ));
  231. }
  232. if ($type && $type !== get_resource_type($value)) {
  233. static::reportInvalidArgument(sprintf(
  234. $message ?: 'Expected a resource of type %2$s. Got: %s',
  235. static::typeToString($value),
  236. $type
  237. ));
  238. }
  239. }
  240. public static function isCallable($value, $message = '')
  241. {
  242. if (!is_callable($value)) {
  243. static::reportInvalidArgument(sprintf(
  244. $message ?: 'Expected a callable. Got: %s',
  245. static::typeToString($value)
  246. ));
  247. }
  248. }
  249. public static function isArray($value, $message = '')
  250. {
  251. if (!is_array($value)) {
  252. static::reportInvalidArgument(sprintf(
  253. $message ?: 'Expected an array. Got: %s',
  254. static::typeToString($value)
  255. ));
  256. }
  257. }
  258. public static function isTraversable($value, $message = '')
  259. {
  260. if (!is_array($value) && !($value instanceof Traversable)) {
  261. static::reportInvalidArgument(sprintf(
  262. $message ?: 'Expected a traversable. Got: %s',
  263. static::typeToString($value)
  264. ));
  265. }
  266. }
  267. public static function isInstanceOf($value, $class, $message = '')
  268. {
  269. if (!($value instanceof $class)) {
  270. static::reportInvalidArgument(sprintf(
  271. $message ?: 'Expected an instance of %2$s. Got: %s',
  272. static::typeToString($value),
  273. $class
  274. ));
  275. }
  276. }
  277. public static function notInstanceOf($value, $class, $message = '')
  278. {
  279. if ($value instanceof $class) {
  280. static::reportInvalidArgument(sprintf(
  281. $message ?: 'Expected an instance other than %2$s. Got: %s',
  282. static::typeToString($value),
  283. $class
  284. ));
  285. }
  286. }
  287. public static function isEmpty($value, $message = '')
  288. {
  289. if (!empty($value)) {
  290. static::reportInvalidArgument(sprintf(
  291. $message ?: 'Expected an empty value. Got: %s',
  292. static::valueToString($value)
  293. ));
  294. }
  295. }
  296. public static function notEmpty($value, $message = '')
  297. {
  298. if (empty($value)) {
  299. static::reportInvalidArgument(sprintf(
  300. $message ?: 'Expected a non-empty value. Got: %s',
  301. static::valueToString($value)
  302. ));
  303. }
  304. }
  305. public static function null($value, $message = '')
  306. {
  307. if (null !== $value) {
  308. static::reportInvalidArgument(sprintf(
  309. $message ?: 'Expected null. Got: %s',
  310. static::valueToString($value)
  311. ));
  312. }
  313. }
  314. public static function notNull($value, $message = '')
  315. {
  316. if (null === $value) {
  317. static::reportInvalidArgument(
  318. $message ?: 'Expected a value other than null.'
  319. );
  320. }
  321. }
  322. public static function true($value, $message = '')
  323. {
  324. if (true !== $value) {
  325. static::reportInvalidArgument(sprintf(
  326. $message ?: 'Expected a value to be true. Got: %s',
  327. static::valueToString($value)
  328. ));
  329. }
  330. }
  331. public static function false($value, $message = '')
  332. {
  333. if (false !== $value) {
  334. static::reportInvalidArgument(sprintf(
  335. $message ?: 'Expected a value to be false. Got: %s',
  336. static::valueToString($value)
  337. ));
  338. }
  339. }
  340. public static function eq($value, $value2, $message = '')
  341. {
  342. if ($value2 != $value) {
  343. static::reportInvalidArgument(sprintf(
  344. $message ?: 'Expected a value equal to %2$s. Got: %s',
  345. static::valueToString($value),
  346. static::valueToString($value2)
  347. ));
  348. }
  349. }
  350. public static function notEq($value, $value2, $message = '')
  351. {
  352. if ($value2 == $value) {
  353. static::reportInvalidArgument(sprintf(
  354. $message ?: 'Expected a different value than %s.',
  355. static::valueToString($value2)
  356. ));
  357. }
  358. }
  359. public static function same($value, $value2, $message = '')
  360. {
  361. if ($value2 !== $value) {
  362. static::reportInvalidArgument(sprintf(
  363. $message ?: 'Expected a value identical to %2$s. Got: %s',
  364. static::valueToString($value),
  365. static::valueToString($value2)
  366. ));
  367. }
  368. }
  369. public static function notSame($value, $value2, $message = '')
  370. {
  371. if ($value2 === $value) {
  372. static::reportInvalidArgument(sprintf(
  373. $message ?: 'Expected a value not identical to %s.',
  374. static::valueToString($value2)
  375. ));
  376. }
  377. }
  378. public static function greaterThan($value, $limit, $message = '')
  379. {
  380. if ($value <= $limit) {
  381. static::reportInvalidArgument(sprintf(
  382. $message ?: 'Expected a value greater than %2$s. Got: %s',
  383. static::valueToString($value),
  384. static::valueToString($limit)
  385. ));
  386. }
  387. }
  388. public static function greaterThanEq($value, $limit, $message = '')
  389. {
  390. if ($value < $limit) {
  391. static::reportInvalidArgument(sprintf(
  392. $message ?: 'Expected a value greater than or equal to %2$s. Got: %s',
  393. static::valueToString($value),
  394. static::valueToString($limit)
  395. ));
  396. }
  397. }
  398. public static function lessThan($value, $limit, $message = '')
  399. {
  400. if ($value >= $limit) {
  401. static::reportInvalidArgument(sprintf(
  402. $message ?: 'Expected a value less than %2$s. Got: %s',
  403. static::valueToString($value),
  404. static::valueToString($limit)
  405. ));
  406. }
  407. }
  408. public static function lessThanEq($value, $limit, $message = '')
  409. {
  410. if ($value > $limit) {
  411. static::reportInvalidArgument(sprintf(
  412. $message ?: 'Expected a value less than or equal to %2$s. Got: %s',
  413. static::valueToString($value),
  414. static::valueToString($limit)
  415. ));
  416. }
  417. }
  418. public static function range($value, $min, $max, $message = '')
  419. {
  420. if ($value < $min || $value > $max) {
  421. static::reportInvalidArgument(sprintf(
  422. $message ?: 'Expected a value between %2$s and %3$s. Got: %s',
  423. static::valueToString($value),
  424. static::valueToString($min),
  425. static::valueToString($max)
  426. ));
  427. }
  428. }
  429. public static function oneOf($value, array $values, $message = '')
  430. {
  431. if (!in_array($value, $values, true)) {
  432. static::reportInvalidArgument(sprintf(
  433. $message ?: 'Expected one of: %2$s. Got: %s',
  434. static::valueToString($value),
  435. implode(', ', array_map(array('static', 'valueToString'), $values))
  436. ));
  437. }
  438. }
  439. public static function contains($value, $subString, $message = '')
  440. {
  441. if (false === strpos($value, $subString)) {
  442. static::reportInvalidArgument(sprintf(
  443. $message ?: 'Expected a value to contain %2$s. Got: %s',
  444. static::valueToString($value),
  445. static::valueToString($subString)
  446. ));
  447. }
  448. }
  449. public static function startsWith($value, $prefix, $message = '')
  450. {
  451. if (0 !== strpos($value, $prefix)) {
  452. static::reportInvalidArgument(sprintf(
  453. $message ?: 'Expected a value to start with %2$s. Got: %s',
  454. static::valueToString($value),
  455. static::valueToString($prefix)
  456. ));
  457. }
  458. }
  459. public static function startsWithLetter($value, $message = '')
  460. {
  461. $valid = isset($value[0]);
  462. if ($valid) {
  463. $locale = setlocale(LC_CTYPE, 0);
  464. setlocale(LC_CTYPE, 'C');
  465. $valid = ctype_alpha($value[0]);
  466. setlocale(LC_CTYPE, $locale);
  467. }
  468. if (!$valid) {
  469. static::reportInvalidArgument(sprintf(
  470. $message ?: 'Expected a value to start with a letter. Got: %s',
  471. static::valueToString($value)
  472. ));
  473. }
  474. }
  475. public static function endsWith($value, $suffix, $message = '')
  476. {
  477. if ($suffix !== substr($value, -static::strlen($suffix))) {
  478. static::reportInvalidArgument(sprintf(
  479. $message ?: 'Expected a value to end with %2$s. Got: %s',
  480. static::valueToString($value),
  481. static::valueToString($suffix)
  482. ));
  483. }
  484. }
  485. public static function regex($value, $pattern, $message = '')
  486. {
  487. if (!preg_match($pattern, $value)) {
  488. static::reportInvalidArgument(sprintf(
  489. $message ?: 'The value %s does not match the expected pattern.',
  490. static::valueToString($value)
  491. ));
  492. }
  493. }
  494. public static function alpha($value, $message = '')
  495. {
  496. $locale = setlocale(LC_CTYPE, 0);
  497. setlocale(LC_CTYPE, 'C');
  498. $valid = !ctype_alpha($value);
  499. setlocale(LC_CTYPE, $locale);
  500. if ($valid) {
  501. static::reportInvalidArgument(sprintf(
  502. $message ?: 'Expected a value to contain only letters. Got: %s',
  503. static::valueToString($value)
  504. ));
  505. }
  506. }
  507. public static function digits($value, $message = '')
  508. {
  509. $locale = setlocale(LC_CTYPE, 0);
  510. setlocale(LC_CTYPE, 'C');
  511. $valid = !ctype_digit($value);
  512. setlocale(LC_CTYPE, $locale);
  513. if ($valid) {
  514. static::reportInvalidArgument(sprintf(
  515. $message ?: 'Expected a value to contain digits only. Got: %s',
  516. static::valueToString($value)
  517. ));
  518. }
  519. }
  520. public static function alnum($value, $message = '')
  521. {
  522. $locale = setlocale(LC_CTYPE, 0);
  523. setlocale(LC_CTYPE, 'C');
  524. $valid = !ctype_alnum($value);
  525. setlocale(LC_CTYPE, $locale);
  526. if ($valid) {
  527. static::reportInvalidArgument(sprintf(
  528. $message ?: 'Expected a value to contain letters and digits only. Got: %s',
  529. static::valueToString($value)
  530. ));
  531. }
  532. }
  533. public static function lower($value, $message = '')
  534. {
  535. $locale = setlocale(LC_CTYPE, 0);
  536. setlocale(LC_CTYPE, 'C');
  537. $valid = !ctype_lower($value);
  538. setlocale(LC_CTYPE, $locale);
  539. if ($valid) {
  540. static::reportInvalidArgument(sprintf(
  541. $message ?: 'Expected a value to contain lowercase characters only. Got: %s',
  542. static::valueToString($value)
  543. ));
  544. }
  545. }
  546. public static function upper($value, $message = '')
  547. {
  548. $locale = setlocale(LC_CTYPE, 0);
  549. setlocale(LC_CTYPE, 'C');
  550. $valid = !ctype_upper($value);
  551. setlocale(LC_CTYPE, $locale);
  552. if ($valid) {
  553. static::reportInvalidArgument(sprintf(
  554. $message ?: 'Expected a value to contain uppercase characters only. Got: %s',
  555. static::valueToString($value)
  556. ));
  557. }
  558. }
  559. public static function length($value, $length, $message = '')
  560. {
  561. if ($length !== static::strlen($value)) {
  562. static::reportInvalidArgument(sprintf(
  563. $message ?: 'Expected a value to contain %2$s characters. Got: %s',
  564. static::valueToString($value),
  565. $length
  566. ));
  567. }
  568. }
  569. public static function minLength($value, $min, $message = '')
  570. {
  571. if (static::strlen($value) < $min) {
  572. static::reportInvalidArgument(sprintf(
  573. $message ?: 'Expected a value to contain at least %2$s characters. Got: %s',
  574. static::valueToString($value),
  575. $min
  576. ));
  577. }
  578. }
  579. public static function maxLength($value, $max, $message = '')
  580. {
  581. if (static::strlen($value) > $max) {
  582. static::reportInvalidArgument(sprintf(
  583. $message ?: 'Expected a value to contain at most %2$s characters. Got: %s',
  584. static::valueToString($value),
  585. $max
  586. ));
  587. }
  588. }
  589. public static function lengthBetween($value, $min, $max, $message = '')
  590. {
  591. $length = static::strlen($value);
  592. if ($length < $min || $length > $max) {
  593. static::reportInvalidArgument(sprintf(
  594. $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s',
  595. static::valueToString($value),
  596. $min,
  597. $max
  598. ));
  599. }
  600. }
  601. public static function fileExists($value, $message = '')
  602. {
  603. static::string($value);
  604. if (!file_exists($value)) {
  605. static::reportInvalidArgument(sprintf(
  606. $message ?: 'The file %s does not exist.',
  607. static::valueToString($value)
  608. ));
  609. }
  610. }
  611. public static function file($value, $message = '')
  612. {
  613. static::fileExists($value, $message);
  614. if (!is_file($value)) {
  615. static::reportInvalidArgument(sprintf(
  616. $message ?: 'The path %s is not a file.',
  617. static::valueToString($value)
  618. ));
  619. }
  620. }
  621. public static function directory($value, $message = '')
  622. {
  623. static::fileExists($value, $message);
  624. if (!is_dir($value)) {
  625. static::reportInvalidArgument(sprintf(
  626. $message ?: 'The path %s is no directory.',
  627. static::valueToString($value)
  628. ));
  629. }
  630. }
  631. public static function readable($value, $message = '')
  632. {
  633. if (!is_readable($value)) {
  634. static::reportInvalidArgument(sprintf(
  635. $message ?: 'The path %s is not readable.',
  636. static::valueToString($value)
  637. ));
  638. }
  639. }
  640. public static function writable($value, $message = '')
  641. {
  642. if (!is_writable($value)) {
  643. static::reportInvalidArgument(sprintf(
  644. $message ?: 'The path %s is not writable.',
  645. static::valueToString($value)
  646. ));
  647. }
  648. }
  649. public static function classExists($value, $message = '')
  650. {
  651. if (!class_exists($value)) {
  652. static::reportInvalidArgument(sprintf(
  653. $message ?: 'Expected an existing class name. Got: %s',
  654. static::valueToString($value)
  655. ));
  656. }
  657. }
  658. public static function subclassOf($value, $class, $message = '')
  659. {
  660. if (!is_subclass_of($value, $class)) {
  661. static::reportInvalidArgument(sprintf(
  662. $message ?: 'Expected a sub-class of %2$s. Got: %s',
  663. static::valueToString($value),
  664. static::valueToString($class)
  665. ));
  666. }
  667. }
  668. public static function implementsInterface($value, $interface, $message = '')
  669. {
  670. if (!in_array($interface, class_implements($value))) {
  671. static::reportInvalidArgument(sprintf(
  672. $message ?: 'Expected an implementation of %2$s. Got: %s',
  673. static::valueToString($value),
  674. static::valueToString($interface)
  675. ));
  676. }
  677. }
  678. public static function propertyExists($classOrObject, $property, $message = '')
  679. {
  680. if (!property_exists($classOrObject, $property)) {
  681. static::reportInvalidArgument(sprintf(
  682. $message ?: 'Expected the property %s to exist.',
  683. static::valueToString($property)
  684. ));
  685. }
  686. }
  687. public static function propertyNotExists($classOrObject, $property, $message = '')
  688. {
  689. if (property_exists($classOrObject, $property)) {
  690. static::reportInvalidArgument(sprintf(
  691. $message ?: 'Expected the property %s to not exist.',
  692. static::valueToString($property)
  693. ));
  694. }
  695. }
  696. public static function methodExists($classOrObject, $method, $message = '')
  697. {
  698. if (!method_exists($classOrObject, $method)) {
  699. static::reportInvalidArgument(sprintf(
  700. $message ?: 'Expected the method %s to exist.',
  701. static::valueToString($method)
  702. ));
  703. }
  704. }
  705. public static function methodNotExists($classOrObject, $method, $message = '')
  706. {
  707. if (method_exists($classOrObject, $method)) {
  708. static::reportInvalidArgument(sprintf(
  709. $message ?: 'Expected the method %s to not exist.',
  710. static::valueToString($method)
  711. ));
  712. }
  713. }
  714. public static function keyExists($array, $key, $message = '')
  715. {
  716. if (!array_key_exists($key, $array)) {
  717. static::reportInvalidArgument(sprintf(
  718. $message ?: 'Expected the key %s to exist.',
  719. static::valueToString($key)
  720. ));
  721. }
  722. }
  723. public static function keyNotExists($array, $key, $message = '')
  724. {
  725. if (array_key_exists($key, $array)) {
  726. static::reportInvalidArgument(sprintf(
  727. $message ?: 'Expected the key %s to not exist.',
  728. static::valueToString($key)
  729. ));
  730. }
  731. }
  732. public static function count($array, $number, $message = '')
  733. {
  734. static::eq(
  735. count($array),
  736. $number,
  737. $message ?: sprintf('Expected an array to contain %d elements. Got: %d.', $number, count($array))
  738. );
  739. }
  740. public static function uuid($value, $message = '')
  741. {
  742. $value = str_replace(array('urn:', 'uuid:', '{', '}'), '', $value);
  743. // The nil UUID is special form of UUID that is specified to have all
  744. // 128 bits set to zero.
  745. if ('00000000-0000-0000-0000-000000000000' === $value) {
  746. return;
  747. }
  748. if (!preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) {
  749. static::reportInvalidArgument(sprintf(
  750. $message ?: 'Value %s is not a valid UUID.',
  751. static::valueToString($value)
  752. ));
  753. }
  754. }
  755. public static function throws(Closure $expression, $class = 'Exception', $message = '')
  756. {
  757. static::string($class);
  758. $actual = 'none';
  759. try {
  760. $expression();
  761. } catch (Exception $e) {
  762. $actual = get_class($e);
  763. if ($e instanceof $class) {
  764. return;
  765. }
  766. } catch (Throwable $e) {
  767. $actual = get_class($e);
  768. if ($e instanceof $class) {
  769. return;
  770. }
  771. }
  772. static::reportInvalidArgument($message ?: sprintf(
  773. 'Expected to throw "%s", got "%s"',
  774. $class,
  775. $actual
  776. ));
  777. }
  778. public static function __callStatic($name, $arguments)
  779. {
  780. if ('nullOr' === substr($name, 0, 6)) {
  781. if (null !== $arguments[0]) {
  782. $method = lcfirst(substr($name, 6));
  783. call_user_func_array(array('static', $method), $arguments);
  784. }
  785. return;
  786. }
  787. if ('all' === substr($name, 0, 3)) {
  788. static::isTraversable($arguments[0]);
  789. $method = lcfirst(substr($name, 3));
  790. $args = $arguments;
  791. foreach ($arguments[0] as $entry) {
  792. $args[0] = $entry;
  793. call_user_func_array(array('static', $method), $args);
  794. }
  795. return;
  796. }
  797. throw new BadMethodCallException('No such method: '.$name);
  798. }
  799. protected static function valueToString($value)
  800. {
  801. if (null === $value) {
  802. return 'null';
  803. }
  804. if (true === $value) {
  805. return 'true';
  806. }
  807. if (false === $value) {
  808. return 'false';
  809. }
  810. if (is_array($value)) {
  811. return 'array';
  812. }
  813. if (is_object($value)) {
  814. return get_class($value);
  815. }
  816. if (is_resource($value)) {
  817. return 'resource';
  818. }
  819. if (is_string($value)) {
  820. return '"'.$value.'"';
  821. }
  822. return (string) $value;
  823. }
  824. protected static function typeToString($value)
  825. {
  826. return is_object($value) ? get_class($value) : gettype($value);
  827. }
  828. protected static function strlen($value)
  829. {
  830. if (!function_exists('mb_detect_encoding')) {
  831. return strlen($value);
  832. }
  833. if (false === $encoding = mb_detect_encoding($value)) {
  834. return strlen($value);
  835. }
  836. return mb_strwidth($value, $encoding);
  837. }
  838. protected static function reportInvalidArgument($message)
  839. {
  840. throw new InvalidArgumentException($message);
  841. }
  842. private function __construct()
  843. {
  844. }
  845. }