Completed
Push — riccardonar-master ( 93b139 )
by Asmir
02:15
created

Client   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 12

Test Coverage

Coverage 96.61%

Importance

Changes 0
Metric Value
wmc 16
lcom 0
cbo 12
dl 0
loc 125
ccs 57
cts 59
cp 0.9661
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
B __call() 0 49 6
A findFaultClass() 0 8 2
A buildHeaders() 0 9 3
A findOperation() 0 13 4
1
<?php
2
3
namespace GoetasWebservices\SoapServices\SoapClient;
4
5
use GoetasWebservices\SoapServices\SoapClient\Arguments\ArgumentsReader;
6
use GoetasWebservices\SoapServices\SoapClient\Arguments\ArgumentsReaderInterface;
7
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderHandler;
8
use GoetasWebservices\SoapServices\SoapClient\Envelope\SoapEnvelope\Messages\Fault as Fault11;
9
use GoetasWebservices\SoapServices\SoapClient\Envelope\SoapEnvelope12\Messages\Fault as Fault12;
10
use GoetasWebservices\SoapServices\SoapClient\Exception\ClientException;
11
use GoetasWebservices\SoapServices\SoapClient\Exception\ServerException;
12
use GoetasWebservices\SoapServices\SoapClient\Exception\SoapException;
13
use GoetasWebservices\SoapServices\SoapClient\Exception\UnexpectedFormatException;
14
use GoetasWebservices\SoapServices\SoapClient\Result\ResultCreator;
15
use GoetasWebservices\SoapServices\SoapClient\Result\ResultCreatorInterface;
16
use GoetasWebservices\SoapServices\SoapEnvelope;
17
use Http\Client\Exception\HttpException;
18
use Http\Client\HttpClient;
19
use Http\Message\MessageFactory;
20
use JMS\Serializer\Serializer;
21
use Psr\Http\Message\ResponseInterface;
22
23
class Client
24
{
25
    /**
26
     * @var Serializer
27
     */
28
    protected $serializer;
29
    /**
30
     * @var array
31
     */
32
    protected $serviceDefinition;
33
    /**
34
     * @var HttpClient
35
     */
36
    protected $client;
37
38
    /**
39
     * @var MessageFactory
40
     */
41
    protected $messageFactory;
42
43
    /**
44
     * @var ResultCreatorInterface
45
     */
46
    private $resultCreator;
47
48
    /**
49
     * @var ArgumentsReaderInterface
50
     */
51
    private $argumentsReader;
52
53
54 32
    public function __construct(array $serviceDefinition, Serializer $serializer, MessageFactory $messageFactory, HttpClient $client, HeaderHandler $headerHandler)
55 1
    {
56 32
        $this->serviceDefinition = $serviceDefinition;
57 32
        $this->serializer = $serializer;
58
59 32
        $this->client = $client;
60 32
        $this->messageFactory = $messageFactory;
61 32
        $this->argumentsReader = new ArgumentsReader($this->serializer, $headerHandler);
62 32
        $this->resultCreator = new ResultCreator($this->serializer, !empty($serviceDefinition['unwrap']));
63 32
    }
64
65 30
    public function __call($functionName, array $args)
66
    {
67 30
        $soapOperation = $this->findOperation($functionName, $this->serviceDefinition);
68 30
        $message = $this->argumentsReader->readArguments($args, $soapOperation['input']);
69
70 30
        $xmlMessage = $this->serializer->serialize($message, 'xml');
0 ignored issues
show
Bug introduced by
It seems like $message defined by $this->argumentsReader->...soapOperation['input']) on line 68 can also be of type null; however, JMS\Serializer\Serializer::serialize() does only seem to accept object|array|integer|double|string|boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
71 30
        $headers = $this->buildHeaders($soapOperation);
72 30
        $request = $this->messageFactory->createRequest('POST', $this->serviceDefinition['endpoint'], $headers, $xmlMessage);
73
74
        try {
75 30
            $response = $this->client->sendRequest($request);
76 20
            if (strpos($response->getHeaderLine('Content-Type'), 'xml') === false) {
77 2
                throw new UnexpectedFormatException(
78 2
                    $response,
79 2
                    $request,
80 2
                    "Unexpected content type '" . $response->getHeaderLine('Content-Type') . "'"
81 2
                );
82
            }
83
84
            // fast return if no return is expected
85 18
            if (!count($soapOperation['output']['parts'])) {
86 4
                return null;
87
            }
88
89 14
            $body = (string)$response->getBody();
90
91 14
            $faultClass = $this->findFaultClass($response);
92
93 14
            if (strpos($body, ':Fault>') !== false) { // some server returns a fault with 200 OK HTTP
94 1
                $fault = $this->serializer->deserialize($body, $faultClass, 'xml');
95 1
                throw $fault->createException($response, $request);
96
            }
97
98 13
            $response = $this->serializer->deserialize($body, $soapOperation['output']['message_fqcn'], 'xml');
99 26
        } catch (HttpException $e) {
100 10
            if (strpos($e->getResponse()->getHeaderLine('Content-Type'), 'xml') !== false) {
101 6
                $faultClass = $this->findFaultClass($e->getResponse());
102 6
                $fault = $this->serializer->deserialize((string)$e->getResponse()->getBody(), $faultClass, 'xml');
103 6
                throw $fault->createException($e->getResponse(), $e->getRequest(), $e);
104
            } else {
105 4
                throw new ServerException(
106 4
                    $e->getResponse(),
107 4
                    $e->getRequest(),
108
                    $e
109 4
                );
110
            }
111
        }
112 13
        return $this->resultCreator->prepareResult($response, $soapOperation['output']);
113
    }
114
115 20
    public function findFaultClass(ResponseInterface $response)
116 1
    {
117 20
        if (strpos($response->getHeaderLine('Content-Type'), 'application/soap+xml') === 0) {
118 11
            return Fault12::class;
119
        } else {
120 9
            return Fault11::class;
121
        }
122
    }
123
124 30
    protected function buildHeaders(array $operation)
125
    {
126
        return [
127 30
            'Content-Type' => isset($operation['version']) && $operation['version'] === '1.2'
128 30
                ? 'application/soap+xml; charset=utf-8'
129 30
                : 'text/xml; charset=utf-8',
130 30
            'SoapAction' => '"' . $operation['action'] . '"',
131 30
        ];
132
    }
133
134 30
    protected function findOperation($functionName, array $serviceDefinition)
135
    {
136 30
        if (isset($serviceDefinition['operations'][$functionName])) {
137 29
            return $serviceDefinition['operations'][$functionName];
138
        }
139
140 1
        foreach ($serviceDefinition['operations'] as $opName => $operation) {
141 1
            if (strtolower($functionName) == strtolower($opName)) {
142 1
                return $operation;
143
            }
144
        }
145
        throw new ClientException("Can not find an operation to run $functionName service call");
146
    }
147
}
148