1<?php
2/*
3 * This file is part of the PHPUnit_MockObject package.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11/**
12 * Invocation matcher which looks for sets of specific parameters in the invocations.
13 *
14 * Checks the parameters of the incoming invocations, the parameter list is
15 * checked against the defined constraints in $parameters. If the constraint
16 * is met it will return true in matches().
17 *
18 * It takes a list of match groups and and increases a call index after each invocation.
19 * So the first invocation uses the first group of constraints, the second the next and so on.
20 */
21class PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters extends PHPUnit_Framework_MockObject_Matcher_StatelessInvocation
22{
23    /**
24     * @var array
25     */
26    private $parameterGroups = [];
27
28    /**
29     * @var array
30     */
31    private $invocations = [];
32
33    /**
34     * @param array $parameterGroups
35     */
36    public function __construct(array $parameterGroups)
37    {
38        foreach ($parameterGroups as $index => $parameters) {
39            foreach ($parameters as $parameter) {
40                if (!$parameter instanceof PHPUnit_Framework_Constraint) {
41                    $parameter = new PHPUnit_Framework_Constraint_IsEqual($parameter);
42                }
43
44                $this->parameterGroups[$index][] = $parameter;
45            }
46        }
47    }
48
49    /**
50     * @return string
51     */
52    public function toString()
53    {
54        $text = 'with consecutive parameters';
55
56        return $text;
57    }
58
59    /**
60     * @param PHPUnit_Framework_MockObject_Invocation $invocation
61     *
62     * @return bool
63     */
64    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
65    {
66        $this->invocations[] = $invocation;
67        $callIndex           = count($this->invocations) - 1;
68
69        $this->verifyInvocation($invocation, $callIndex);
70
71        return false;
72    }
73
74    public function verify()
75    {
76        foreach ($this->invocations as $callIndex => $invocation) {
77            $this->verifyInvocation($invocation, $callIndex);
78        }
79    }
80
81    /**
82     * Verify a single invocation
83     *
84     * @param PHPUnit_Framework_MockObject_Invocation $invocation
85     * @param int                                     $callIndex
86     *
87     * @throws PHPUnit_Framework_ExpectationFailedException
88     */
89    private function verifyInvocation(PHPUnit_Framework_MockObject_Invocation $invocation, $callIndex)
90    {
91        if (isset($this->parameterGroups[$callIndex])) {
92            $parameters = $this->parameterGroups[$callIndex];
93        } else {
94            // no parameter assertion for this call index
95            return;
96        }
97
98        if ($invocation === null) {
99            throw new PHPUnit_Framework_ExpectationFailedException(
100                'Mocked method does not exist.'
101            );
102        }
103
104        if (count($invocation->parameters) < count($parameters)) {
105            throw new PHPUnit_Framework_ExpectationFailedException(
106                sprintf(
107                    'Parameter count for invocation %s is too low.',
108                    $invocation->toString()
109                )
110            );
111        }
112
113        foreach ($parameters as $i => $parameter) {
114            $parameter->evaluate(
115                $invocation->parameters[$i],
116                sprintf(
117                    'Parameter %s for invocation #%d %s does not match expected ' .
118                    'value.',
119                    $i,
120                    $callIndex,
121                    $invocation->toString()
122                )
123            );
124        }
125    }
126}
127