ArraySubset.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Testing\Constraint;
  12. use ArrayObject;
  13. use PHPUnit\Framework\Constraint\Constraint;
  14. use PHPUnit\Framework\ExpectationFailedException;
  15. use SebastianBergmann\Comparator\ComparisonFailure;
  16. use Traversable;
  17. /**
  18. * @internal this class is not meant to be used or overwritten outside the framework itself
  19. */
  20. final class ArraySubset extends Constraint
  21. {
  22. /**
  23. * @var iterable
  24. */
  25. private $subset;
  26. /**
  27. * @var bool
  28. */
  29. private $strict;
  30. /**
  31. * Create a new array subset constraint instance.
  32. */
  33. public function __construct(iterable $subset, bool $strict = false)
  34. {
  35. $this->strict = $strict;
  36. $this->subset = $subset;
  37. }
  38. /**
  39. * Evaluates the constraint for parameter $other.
  40. *
  41. * If $returnResult is set to false (the default), an exception is thrown
  42. * in case of a failure. null is returned otherwise.
  43. *
  44. * If $returnResult is true, the result of the evaluation is returned as
  45. * a boolean value instead: true in case of success, false in case of a
  46. * failure.
  47. *
  48. * @param mixed $other
  49. *
  50. * @throws ExpectationFailedException
  51. */
  52. public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
  53. {
  54. // type cast $other & $this->subset as an array to allow
  55. // support in standard array functions.
  56. $other = $this->toArray($other);
  57. $this->subset = $this->toArray($this->subset);
  58. $patched = array_replace_recursive($other, $this->subset);
  59. if ($this->strict) {
  60. $result = $other === $patched;
  61. } else {
  62. $result = $other == $patched;
  63. }
  64. if ($returnResult) {
  65. return $result;
  66. }
  67. if (! $result) {
  68. $f = new ComparisonFailure(
  69. $patched,
  70. $other,
  71. var_export($patched, true),
  72. var_export($other, true)
  73. );
  74. $this->fail($other, $description, $f);
  75. }
  76. return null;
  77. }
  78. /**
  79. * Returns a string representation of the constraint.
  80. */
  81. public function toString(): string
  82. {
  83. return 'has the subset ' . $this->exporter()->export($this->subset);
  84. }
  85. /**
  86. * Returns the description of the failure.
  87. *
  88. * The beginning of failure messages is "Failed asserting that" in most
  89. * cases. This method should return the second part of that sentence.
  90. *
  91. * @param mixed $other
  92. */
  93. protected function failureDescription($other): string
  94. {
  95. return 'an array ' . $this->toString();
  96. }
  97. /**
  98. * Returns the description of the failure.
  99. *
  100. * The beginning of failure messages is "Failed asserting that" in most
  101. * cases. This method should return the second part of that sentence.
  102. */
  103. private function toArray(iterable $other): array
  104. {
  105. if ($other instanceof ArrayObject) {
  106. return $other->getArrayCopy();
  107. }
  108. if ($other instanceof Traversable) {
  109. return iterator_to_array($other);
  110. }
  111. return (array) $other;
  112. }
  113. }