ListMatcher::matchesList()
last analyzed

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 1
ccs 0
cts 0
cp 0
nc 1
1
<?php
2
3
/*
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * The software is based on the Axon Framework project which is
17
 * licensed under the Apache 2.0 license. For more information on the Axon Framework
18
 * see <http://www.axonframework.org/>.
19
 * 
20
 * This software consists of voluntary contributions made by many individuals
21
 * and is licensed under the MIT license. For more information, see
22
 * <http://www.governor-framework.org/>.
23
 */
24
25
namespace Governor\Framework\Test\Matchers;
26
27
use Hamcrest\Matcher;
28
use Hamcrest\BaseMatcher;
29
use Hamcrest\Description;
30
31
/**
32
 * Abstract implementation for matchers that use event-specific matchers to match against a list of items.
33
 *
34
 * @author    "David Kalosi" <[email protected]>  
35
 * @license   <a href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> 
36
 */
37
abstract class ListMatcher extends BaseMatcher
38
{
39
    /**     
40
     * @var array
41
     */
42
    private $failedMatchers = array();
43
    
44
    /**     
45
     * @var array
46
     */
47
    private $matchers = array();
48
49
    /**
50
     * Creates an abstract matcher to match a number of Matchers against Events contained inside a Collection.
51
     *
52
     * @param Matcher[] $matchers The matchers to match the individual Events in the Collection
53
     */
54 28
    protected function __construct(array $matchers)
55
    {
56 28
        $this->matchers = $matchers;
57 28
    }
58
59
    /**
60
     * @param mixed $item
61
     * @return bool
62
     */
63 28
    public function matches($item)
64
    {        
65 28
        return is_array($item) && $this->matchesList($item);
66
    }
67
68
    /**
69
     * Evaluates the matcher for argument <code>item</code>. The item has been verified to be a list, but the exact
70
     * type of contents of a list cannot be verified, due to Erasure of Generic Types.
71
     *
72
     * @param array $item the object against which the matcher is evaluated.
73
     * @return boolean <code>true</code> if <code>item</code> matches, otherwise <code>false</code>.
74
     *
75
     * @see BaseMatcher
76
     */
77
    abstract protected function matchesList(array $item);
78
79
    /**
80
     * Matches all the remaining Matchers in the given <code>matcherIterator</code> against <code>null</code>.
81
     *
82
     * @param \Iterator $matcherIterator The iterator potentially containing more matchers
83
     * @return boolean true if no matchers remain or all matchers succeeded
84
     */
85 11
    protected function matchRemainder(\Iterator $matcherIterator)
86
    {        
87 11
        while ($matcherIterator->valid()) {            
88 4
            $matcher = $matcherIterator->current();
89
90 4
            if (!$matcher->matches(null)) {                
91 2
                $this->failedMatchers[] = $matcher;
92 2
                return false;
93
            }
94
95 2
            $matcherIterator->next();
96 2
        }
97
98 9
        return true;
99
    }
100
101
    /**
102
     * Report the given <code>matcher</code> as a failing matcher. This will be used in the error reporting.
103
     *
104
     * @param Matcher $matcher The failing matcher.
105
     */
106 10
    protected function reportFailed(Matcher $matcher)
107
    {
108 10
        $this->failedMatchers[] = $matcher;
109 10
    }
110
111
    /**
112
     * Returns a read-only list of Matchers, in the order they were provided in the constructor.
113
     *
114
     * @return Matcher[] a read-only list of Matchers, in the order they were provided in the constructor
115
     */
116 28
    protected function getMatchers()
117
    {
118 28
        return $this->matchers;
119
    }
120
121
    /**
122
     * Describes the type of collection expected. To be used in the sentence: "list with ... of: <description of
123
     * matchers>". E.g. "all" or "sequence".
124
     *
125
     * @param Description $description the description to append the collection type to
126
     */
127
    protected abstract function describeCollectionType(Description $description);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
128
129 8
    public function describeTo(Description $description)
130
    {
131 8
        $description->appendText("list with ");
132 8
        $this->describeCollectionType($description);
133 8
        $description->appendText(" of: ");
134
135 8
        for ($t = 0; $t < count($this->matchers); $t++) {            
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
136 8
            if ($t !== 0 && $t < count($this->matchers) - 1) {
137 8
                $description->appendText(", ");
138 8
            } else if ($t === count($this->matchers) - 1 && $t > 0) {
139 8
                $description->appendText(" ");
140 8
                $description->appendText($this->getLastSeparator());
141 8
                $description->appendText(" ");
142 8
            }
143
            
144 8
            $description->appendText("<");
145 8
            $this->matchers[$t]->describeTo($description);
146 8
            $description->appendText(">");
147
148 8
            if (in_array($this->matchers[$t], $this->failedMatchers, true)) {
149 4
                $description->appendText(" (");
150 4
                $description->appendText($this->failedMatcherMessage());
151 4
                $description->appendText(")");
152 4
            }
153 8
        }
154 8
    }
155
156
    /**
157
     * The message to append behind a failing matcher. Defaults to FAILED!.
158
     *
159
     * @return string The message to append behind a failing matcher
160
     */
161 3
    protected function failedMatcherMessage()
162
    {
163 3
        return "FAILED!";
164
    }
165
166
    /**
167
     * The separator to use between the two last events. Defaults to "and".
168
     *
169
     * @return string The separator to use between the two last events. Defaults to "and".
170
     */
171 6
    protected function getLastSeparator()
172
    {
173 6
        return "and";
174
    }
175
176
}
177