Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of PHPUnit.
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
namespace PHPUnit\Framework\MockObject;
11
 
12
use function strtolower;
13
use Exception;
14
use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
15
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
16
use Throwable;
17
 
18
/**
19
 * @internal This class is not covered by the backward compatibility promise for PHPUnit
20
 */
21
final class InvocationHandler
22
{
23
    /**
24
     * @var Matcher[]
25
     */
26
    private $matchers = [];
27
 
28
    /**
29
     * @var Matcher[]
30
     */
31
    private $matcherMap = [];
32
 
33
    /**
34
     * @var ConfigurableMethod[]
35
     */
36
    private $configurableMethods;
37
 
38
    /**
39
     * @var bool
40
     */
41
    private $returnValueGeneration;
42
 
43
    /**
44
     * @var Throwable
45
     */
46
    private $deferredError;
47
 
48
    public function __construct(array $configurableMethods, bool $returnValueGeneration)
49
    {
50
        $this->configurableMethods   = $configurableMethods;
51
        $this->returnValueGeneration = $returnValueGeneration;
52
    }
53
 
54
    public function hasMatchers(): bool
55
    {
56
        foreach ($this->matchers as $matcher) {
57
            if ($matcher->hasMatchers()) {
58
                return true;
59
            }
60
        }
61
 
62
        return false;
63
    }
64
 
65
    /**
66
     * Looks up the match builder with identification $id and returns it.
67
     *
68
     * @param string $id The identification of the match builder
69
     */
70
    public function lookupMatcher(string $id): ?Matcher
71
    {
72
        if (isset($this->matcherMap[$id])) {
73
            return $this->matcherMap[$id];
74
        }
75
 
76
        return null;
77
    }
78
 
79
    /**
80
     * Registers a matcher with the identification $id. The matcher can later be
81
     * looked up using lookupMatcher() to figure out if it has been invoked.
82
     *
83
     * @param string  $id      The identification of the matcher
84
     * @param Matcher $matcher The builder which is being registered
85
     *
86
     * @throws MatcherAlreadyRegisteredException
87
     */
88
    public function registerMatcher(string $id, Matcher $matcher): void
89
    {
90
        if (isset($this->matcherMap[$id])) {
91
            throw new MatcherAlreadyRegisteredException($id);
92
        }
93
 
94
        $this->matcherMap[$id] = $matcher;
95
    }
96
 
97
    public function expects(InvocationOrder $rule): InvocationMocker
98
    {
99
        $matcher = new Matcher($rule);
100
        $this->addMatcher($matcher);
101
 
102
        return new InvocationMocker(
103
            $this,
104
            $matcher,
105
            ...$this->configurableMethods
106
        );
107
    }
108
 
109
    /**
110
     * @throws Exception
111
     * @throws RuntimeException
112
     */
113
    public function invoke(Invocation $invocation)
114
    {
115
        $exception      = null;
116
        $hasReturnValue = false;
117
        $returnValue    = null;
118
 
119
        foreach ($this->matchers as $match) {
120
            try {
121
                if ($match->matches($invocation)) {
122
                    $value = $match->invoked($invocation);
123
 
124
                    if (!$hasReturnValue) {
125
                        $returnValue    = $value;
126
                        $hasReturnValue = true;
127
                    }
128
                }
129
            } catch (Exception $e) {
130
                $exception = $e;
131
            }
132
        }
133
 
134
        if ($exception !== null) {
135
            throw $exception;
136
        }
137
 
138
        if ($hasReturnValue) {
139
            return $returnValue;
140
        }
141
 
142
        if (!$this->returnValueGeneration) {
143
            $exception = new ReturnValueNotConfiguredException($invocation);
144
 
145
            if (strtolower($invocation->getMethodName()) === '__tostring') {
146
                $this->deferredError = $exception;
147
 
148
                return '';
149
            }
150
 
151
            throw $exception;
152
        }
153
 
154
        return $invocation->generateReturnValue();
155
    }
156
 
157
    public function matches(Invocation $invocation): bool
158
    {
159
        foreach ($this->matchers as $matcher) {
160
            if (!$matcher->matches($invocation)) {
161
                return false;
162
            }
163
        }
164
 
165
        return true;
166
    }
167
 
168
    /**
169
     * @throws Throwable
170
     */
171
    public function verify(): void
172
    {
173
        foreach ($this->matchers as $matcher) {
174
            $matcher->verify();
175
        }
176
 
177
        if ($this->deferredError) {
178
            throw $this->deferredError;
179
        }
180
    }
181
 
182
    private function addMatcher(Matcher $matcher): void
183
    {
184
        $this->matchers[] = $matcher;
185
    }
186
}