Passed
Push — master ( 9bdf5e...def7ed )
by Pol
02:33
created

MockSoapClient::buildIterators()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 15
ccs 7
cts 7
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace loophp\MockSoapClient;
6
7
use ArrayIterator;
8
use InfiniteIterator;
9
use InvalidArgumentException;
10
use SoapClient;
11
use SoapFault;
12
use SoapHeader;
13
14
use function array_key_exists;
15
use function func_get_args;
16
use function is_callable;
17
18
use const ARRAY_FILTER_USE_KEY;
19
20
/**
21
 * Class MockSoapClient.
22
 */
23
class MockSoapClient extends SoapClient
24
{
25
    /**
26
     * @var array<int|string, InfiniteIterator>
27
     */
28
    private $iterators;
29
30
    /**
31
     * MockSoapClient constructor.
32
     *
33
     * @param array<mixed>|callable $responses
34
     */
35 9
    public function __construct($responses = null)
36
    {
37 9
        $responses = (array) $responses;
38
39 9
        if ([] === $responses) {
40 3
            throw new InvalidArgumentException('The response argument cannot be empty.');
41
        }
42
43 6
        $this->iterators = $this->buildIterators($responses);
44 6
    }
45
46
    /**
47
     * @param string $function_name
48
     * @param array<mixed> $arguments
49
     *
50
     * @throws \SoapFault
51
     *
52
     * @return mixed
53
     */
54 3
    public function __call($function_name, $arguments = [])
55
    {
56
        try {
57 3
            $response = $this->__soapCall($function_name, $arguments);
58 1
        } catch (SoapFault $exception) {
59 1
            throw $exception;
60
        }
61
62 2
        return $response;
63
    }
64
65
    /**
66
     * @param string $function_name
67
     * @param array<mixed> $arguments
68
     * @param array<mixed>|null $options
69
     * @param array<mixed>|SoapHeader|null $input_headers
70
     * @param array<mixed>|null $output_headers
71
     *
72
     * @throws SoapFault
73
     *
74
     * @return mixed
75
     */
76 6
    public function __soapCall(
77
        $function_name,
78
        $arguments,
79
        $options = null,
80
        $input_headers = null,
81
        &$output_headers = null
82
    ) {
83 6
        $iterator = true === array_key_exists($function_name, $this->iterators) ?
84 1
            $this->iterators[$function_name] :
85 6
            $this->iterators['*'];
86
87 6
        $response = $iterator->current();
88 6
        $iterator->next();
89
90 6
        if (true === is_callable($response)) {
91 4
            return ($response)(...func_get_args());
92
        }
93
94 3
        if ($response instanceof SoapFault) {
95 1
            throw $response;
96
        }
97
98 2
        return $response;
99
    }
100
101
    /**
102
     * Build a simple Infinite iterator.
103
     *
104
     * @param array<mixed> $data
105
     *
106
     * @return InfiniteIterator
107
     */
108 6
    private function buildIterator(array $data): InfiniteIterator
109
    {
110 6
        $iterator = new InfiniteIterator(new ArrayIterator($data));
111 6
        $iterator->rewind();
112
113 6
        return $iterator;
114
    }
115
116
    /**
117
     * Build the structure of iterators.
118
     *
119
     * @param array<mixed> $data
120
     *
121
     * @return array<int|string, InfiniteIterator>
122
     */
123 6
    private function buildIterators(array $data): array
124
    {
125
        $iterators = [
126 6
            '*' => $this->buildIterator(array_filter($data, 'is_numeric', ARRAY_FILTER_USE_KEY)),
127
        ];
128
129 6
        foreach ($data as $key => $response) {
130 6
            if (true === is_numeric($key)) {
131 6
                continue;
132
            }
133
134 1
            $iterators[$key] = $this->buildIterator((array) $data[$key]);
135
        }
136
137 6
        return $iterators;
138
    }
139
}
140