Passed
Push — master ( 4bfeda...efa341 )
by Kévin
05:01
created

ArraySubset::failureDescription()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint;
15
16
use PHPUnit\Framework\Constraint\Constraint;
17
use PHPUnit\Framework\ExpectationFailedException;
18
use SebastianBergmann\Comparator\ComparisonFailure;
19
use SebastianBergmann\RecursionContext\InvalidArgumentException;
20
21
/**
22
 * Constraint that asserts that the array it is evaluated for has a specified subset.
23
 *
24
 * Uses array_replace_recursive() to check if a key value subset is part of the
25
 * subject array.
26
 *
27
 * Imported from dms/phpunit-arraysubset-asserts, because the original constraint has been deprecated.
28
 *
29
 * @copyright Sebastian Bergmann <[email protected]>
30
 * @copyright Rafael Dohms <[email protected]>
31
 *
32
 * @see https://github.com/sebastianbergmann/phpunit/issues/3494
33
 */
34
final class ArraySubset extends Constraint
35
{
36
    private $subset;
37
    private $strict;
38
39
    public function __construct(iterable $subset, bool $strict = false)
40
    {
41
        $this->strict = $strict;
42
        $this->subset = $subset;
43
    }
44
45
    /**
46
     * Evaluates the constraint for parameter $other.
47
     *
48
     * If $returnResult is set to false (the default), an exception is thrown
49
     * in case of a failure. null is returned otherwise.
50
     *
51
     * If $returnResult is true, the result of the evaluation is returned as
52
     * a boolean value instead: true in case of success, false in case of a
53
     * failure.
54
     *
55
     * @param iterable $other
56
     *
57
     * @throws ExpectationFailedException
58
     * @throws InvalidArgumentException
59
     *
60
     * @return iterable|bool|null
61
     */
62
    public function evaluate($other, string $description = '', bool $returnResult = false)
63
    {
64
        //type cast $other & $this->subset as an array to allow
65
        //support in standard array functions.
66
        $other = $this->toArray($other);
67
        $this->subset = $this->toArray($this->subset);
68
        $patched = array_replace_recursive($other, $this->subset);
69
        if ($this->strict) {
70
            $result = $other === $patched;
71
        } else {
72
            $result = $other == $patched;
73
        }
74
        if ($returnResult) {
75
            return $result;
76
        }
77
        if ($result) {
78
            return null;
79
        }
80
81
        $f = new ComparisonFailure(
82
            $patched,
83
            $other,
84
            var_export($patched, true),
85
            var_export($other, true)
86
        );
87
        $this->fail($other, $description, $f);
88
    }
89
90
    /**
91
     * Returns a string representation of the constraint.
92
     *
93
     * @throws InvalidArgumentException
94
     */
95
    public function toString(): string
96
    {
97
        return 'has the subset '.$this->exporter()->export($this->subset);
98
    }
99
100
    /**
101
     * Returns the description of the failure.
102
     *
103
     * The beginning of failure messages is "Failed asserting that" in most
104
     * cases. This method should return the second part of that sentence.
105
     *
106
     * @param mixed $other evaluated value or object
107
     *
108
     * @throws InvalidArgumentException
109
     */
110
    protected function failureDescription($other): string
111
    {
112
        return 'an array '.$this->toString();
113
    }
114
115
    private function toArray(iterable $other): array
116
    {
117
        if (\is_array($other)) {
118
            return $other;
119
        }
120
        if ($other instanceof \ArrayObject) {
121
            return $other->getArrayCopy();
122
        }
123
        if ($other instanceof \Traversable) {
124
            return iterator_to_array($other);
125
        }
126
        // Keep BC even if we know that array would not be the expected one
127
        return (array) $other;
128
    }
129
}
130