Completed
Push — master ( d8776d...afe412 )
by Robbie
46s queued 25s
created

SSListContains::exporter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Dev\Constraint;
4
5
use PHPUnit\Framework\Constraint\Constraint;
6
use PHPUnit\Framework\ExpectationFailedException;
7
use SebastianBergmann\Exporter\Exporter;
8
use SilverStripe\Dev\SSListExporter;
9
use SilverStripe\Dev\TestOnly;
10
use SilverStripe\ORM\SS_List;
11
use SilverStripe\View\ViewableData;
12
13
if (!class_exists(Constraint::class)) {
14
    return;
15
}
16
17
/**
18
 * Constraint for checking if a SS_List contains items matching the given
19
 * key-value pairs.
20
 */
21
class SSListContains extends Constraint implements TestOnly
22
{
23
    /**
24
     * @var array
25
     */
26
    protected $matches = [];
27
28
    /**
29
     * @var SSListExporter
30
     */
31
    private $exporter;
32
33
    /**
34
     * Check if the list has left over items that don't match
35
     *
36
     * @var bool
37
     */
38
    protected $hasLeftoverItems = false;
39
40
    public function __construct($matches)
41
    {
42
        $this->matches = $matches;
43
    }
44
45
    protected function exporter(): Exporter
46
    {
47
        if ($this->exporter === null) {
48
            $this->exporter = new SSListExporter();
49
        }
50
51
        return $this->exporter;
52
    }
53
54
    /**
55
     * Evaluates the constraint for parameter $other
56
     *
57
     * If $returnResult is set to false (the default), an exception is thrown
58
     * in case of a failure. null is returned otherwise.
59
     *
60
     * If $returnResult is true, the result of the evaluation is returned as
61
     * a boolean value instead: true in case of success, false in case of a
62
     * failure.
63
     *
64
     * @param SS_List $other Value or object to evaluate.
65
     * @param string $description Additional information about the test
66
     * @param bool $returnResult Whether to return a result or throw an exception
67
     *
68
     * @return null|bool
69
     *
70
     * @throws ExpectationFailedException
71
     */
72
    public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
73
    {
74
        $success = true;
75
76
        foreach ($other as $item) {
77
            $this->checkIfItemEvaluatesRemainingMatches($item);
78
        }
79
80
        //we have remaining matches?
81
        if (count($this->matches) !== 0) {
82
            $success = false;
83
            $this->hasLeftoverItems = true;
84
        }
85
86
        if ($returnResult) {
87
            return $success;
88
        }
89
90
        if (!$success) {
91
            $this->fail($other, $description);
92
        }
93
94
        return null;
95
    }
96
97
    /**
98
     * @param ViewableData $item
99
     * @return bool
100
     */
101
    protected function checkIfItemEvaluatesRemainingMatches(ViewableData $item) : bool
102
    {
103
        $success = false;
104
        foreach ($this->matches as $key => $match) {
105
            $constraint = new ViewableDataContains($match);
106
107
            if ($constraint->evaluate($item, '', true)) {
108
                $success = true;
109
                unset($this->matches[$key]);
110
                break;
111
            }
112
        }
113
114
        return $success;
115
    }
116
117
    /**
118
     * Returns a string representation of the object.
119
     *
120
     * @return string
121
     */
122
    public function toString() : string
123
    {
124
        $matchToString = function ($key, $value) {
125
            return ' "' . $key . '" is "' . $value . '"';
126
        };
127
128
        $matchesToString = function ($matches) use ($matchToString) {
129
            $matchesAsString = implode(' and ', array_map(
130
                $matchToString,
131
                array_keys($matches),
132
                array_values($matches)
133
            ));
134
135
            return '(' . $matchesAsString . ')';
136
        };
137
138
        $allMatchesAsString = implode(
139
            "\n or ",
140
            array_map($matchesToString, $this->matches)
141
        );
142
143
144
        return $this->getStubForToString() . $allMatchesAsString;
145
    }
146
147
    protected function getStubForToString() : string
148
    {
149
        return ' contains an item matching ';
150
    }
151
}
152