ExpectationsFactory::createExpectations()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace Nopolabs\Test;
5
6
use PHPUnit\Framework\TestCase;
7
use PHPUnit_Framework_MockObject_Matcher_Invocation;
8
9
class ExpectationsFactory
10
{
11
    /** @var InvocationFactory */
12
    private $invocationFactory;
13
14
    public function __construct(InvocationFactory $invocationFactory)
15
    {
16
        $this->invocationFactory = $invocationFactory;
17
    }
18
19
    public function createExpectations(array $expectations) : Expectations
20
    {
21
        if ($this->isAssociative($expectations)) {
22
            return $this->buildExpectationsMap($expectations);
23
        }
24
25
        return $this->buildExpectationsList($expectations);
26
    }
27
28
    protected function buildExpectation(
29
        string $method,
30
        array $params,
31
        $result,
32
        $throws,
33
        $invoked) : Expectation
34
    {
35
        $invocation = $this->invocationFactory->prepareInvocation($invoked);
36
37
        return $this->newExpectation($method, $params, $result, $throws, $invocation);
38
    }
39
40
    protected function newExpectation(
41
        string $method,
42
        array $params,
43
        $result,
44
        $throws,
45
        PHPUnit_Framework_MockObject_Matcher_Invocation $invocation) : Expectation
46
    {
47
        return new Expectation($method, $params, $result, $throws, $invocation);
48
    }
49
50
    protected function newExpectations(array $expectations) : Expectations
51
    {
52
        return new Expectations($expectations);
53
    }
54
55
    private function buildExpectationsMap(array $map) : Expectations
56
    {
57
        $expectations = [];
58
59
        foreach ($map as $method => $expects) {
60
            if (!\is_array($expects)) {
61
                $expects = ['invoked' => $expects];
62
            }
63
            $expects['method'] = $method;
64
            list($method, $params, $result, $throws, $invoked) = $this->normalizeExpectation($expects);
65
            $expectations[] = $this->buildExpectation($method, $params, $result, $throws, $invoked);
66
        }
67
68
        return $this->newExpectations($expectations);
69
    }
70
71
    private function buildExpectationsList(array $list) : Expectations
72
    {
73
        $expectations = [];
74
75
        $index = 0;
76
        foreach ($list as $expectation) {
77
            list($method, $params, $result, $throws, $invoked) = $this->normalizeExpectation((array)$expectation);
78
            $invoked = $invoked ?? TestCase::at($index++);
79
            $expectations[] = $this->buildExpectation($method, $params, $result, $throws, $invoked);
80
        }
81
82
        return $this->newExpectations($expectations);
83
    }
84
85
    private function normalizeExpectation(array $expects) : array
86
    {
87
        $method = $expects['method'] ?? null;
88
        $params = $expects['params'] ?? null;
89
        $result = $expects['result'] ?? null;
90
        $throws = $expects['throws'] ?? null;
91
        $invoked = $expects['invoked'] ?? null;
92
93
        unset(
94
            $expects['method'],
95
            $expects['params'],
96
            $expects['result'],
97
            $expects['throws'],
98
            $expects['invoked']
99
        );
100
101
        $method = (string)($method ?? array_shift($expects));
102
        if ($invoked === null && $expects === ['never']) {
103
            $invoked = array_shift($expects);
104
        }
105
        $params = (array)($params ?? array_shift($expects));
106
        $result = $result ?? array_shift($expects);
107
        $throws = $throws ?? array_shift($expects);
108
        $invoked = $invoked ?? array_shift($expects);
109
110
        if ($result !== null && $throws !== null) {
111
            throw new TestException("cannot expect both 'result' and 'throws'");
112
        }
113
114
        return [$method, $params, $result, $throws, $invoked];
115
    }
116
117
    private function isAssociative(array $array) : bool
118
    {
119
        return array_keys($array) !== range(0, \count($array) - 1);
120
    }
121
}
122