MockSoapClient::__call()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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