Passed
Push — master ( e28714...75c076 )
by Daniel
02:16 queued 12s
created

NovaSearchPartnerMethod::createRequestBody()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 47
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 33
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 47
ccs 34
cts 34
cp 1
crap 2
rs 9.392
1
<?php
2
3
namespace OrcaServices\NovaApi\Method;
4
5
use Cake\Chronos\Chronos;
6
use DOMDocument;
7
use DOMElement;
8
use Exception;
9
use OrcaServices\NovaApi\Parameter\NovaSearchPartnerParameter;
10
use OrcaServices\NovaApi\Parser\NovaApiErrorParser;
11
use OrcaServices\NovaApi\Parser\NovaMessageParser;
12
use OrcaServices\NovaApi\Result\NovaPartner;
13
use OrcaServices\NovaApi\Result\NovaSearchPartnerResult;
14
use OrcaServices\NovaApi\Soap\NovaApiSoapAction;
15
use OrcaServices\NovaApi\Soap\NovaParameterMap;
16
use OrcaServices\NovaApi\Soap\NovaParameterWriter;
17
use OrcaServices\NovaApi\Type\GenderType;
18
use OrcaServices\NovaApi\Xml\XmlDocument;
19
20
/**
21
 * SOAP method.
22
 */
23
final class NovaSearchPartnerMethod implements NovaMethod
24
{
25
    /**
26
     * @var NovaApiSoapAction
27
     */
28
    private $novaSoapAction;
29
30
    /**
31
     * @var NovaApiErrorParser
32
     */
33
    private $novaErrorParser;
34
35
    /**
36
     * @var NovaMessageParser
37
     */
38
    private $novaMessageParser;
39
40
    /**
41
     * NovaSearchPartnerMethod constructor.
42
     *
43
     * @param NovaApiSoapAction $novaSoapAction The novaSoapAction
44
     * @param NovaApiErrorParser $novaErrorParser The novaErrorParser
45
     * @param NovaMessageParser $novaMessageParser The message parser
46
     */
47 11
    public function __construct(
48
        NovaApiSoapAction $novaSoapAction,
49
        NovaApiErrorParser $novaErrorParser,
50
        NovaMessageParser $novaMessageParser
51
    ) {
52 11
        $this->novaSoapAction = $novaSoapAction;
53 11
        $this->novaErrorParser = $novaErrorParser;
54 11
        $this->novaMessageParser = $novaMessageParser;
55 11
    }
56
57
    /**
58
     * Search a NOVA partner (customer).
59
     *
60
     * https://confluence-ext.sbb.ch/display/NOVAUG/suchePartner
61
     *
62
     * @param NovaSearchPartnerParameter $parameter The parameters
63
     *
64
     * @return NovaSearchPartnerResult the partners matching the search parameter
65
     * @throws Exception if an error occurs
66
     *
67
     */
68 3
    public function searchPartner(NovaSearchPartnerParameter $parameter): NovaSearchPartnerResult
69
    {
70
        // The SOAP endpoint url
71
        // https://echo-api.3scale.net/novagp/geschaeftspartner/public/MAJOR.MINOR/GeschaeftspartnerService
72 3
        $url = $this->novaSoapAction->getNovaBusinessPartnerServiceUrl();
73
74
        // The SOAP action (http header)
75 3
        $soapAction = $this->novaSoapAction->getSoapAction('geschaeftspartner', 'suchePartner');
76
77
        // The SOAP content (http body)
78 3
        $body = $this->createRequestBody($parameter);
79
80
        try {
81 3
            $xmlContent = $this->novaSoapAction->invokeSoapRequest($url, $soapAction, $body);
82 3
            $xml = XmlDocument::createFromXmlString($xmlContent);
83
84 3
            return $this->createResult($xml);
85
        } catch (Exception $exception) {
86
            throw $this->novaErrorParser->createGeneralException($exception);
87
        }
88
    }
89
90
    /**
91
     * Create SOAP body XML content.
92
     *
93
     * @param NovaSearchPartnerParameter $parameter The parameters
94
     *
95
     * @return string The xml content
96
     */
97 3
    private function createRequestBody(NovaSearchPartnerParameter $parameter): string
98
    {
99 3
        $dom = new DOMDocument('1.0', 'utf-8');
100 3
        $dom->formatOutput = true;
101
102 3
        $dom->appendChild($dom->createComment(' powered by Barakuda '));
103
104 3
        $envelope = $dom->createElement('soapenv:Envelope');
105 3
        $dom->appendChild($envelope);
106 3
        $envelope->setAttribute('xmlns:soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
107
108 3
        $soapHeader = $dom->createElement('soapenv:Header');
109 3
        $envelope->appendChild($soapHeader);
110
111 3
        $body = $dom->createElement('soapenv:Body');
112 3
        $envelope->appendChild($body);
113
114 3
        $method = $dom->createElement('novagp:suchePartner');
115 3
        $body->appendChild($method);
116
117 3
        $this->novaSoapAction->appendMethodNamespaces($method);
118 3
        $this->novaSoapAction->appendDomClientIdentifier($dom, $method, $parameter, 'novagp:');
119 3
        $this->novaSoapAction->appendDomCorrelationContext($dom, $method, $parameter, 'novagp:');
120
121 3
        $partnerSearchParameter = $dom->createElement('novagp:partnerSuchParameter');
122 3
        $method->appendChild($partnerSearchParameter);
123
124 3
        $parameterWriter = new NovaParameterWriter($dom, $partnerSearchParameter);
125
126 3
        $parameterWriter->appendToDocument(new NovaParameterMap([
127 3
            'tkid' => $parameter->tkId,
128 3
            'grundkartenNummer' => $parameter->cardNumber,
129 3
            'ckm' => $parameter->ckm,
130 3
            'name' => $parameter->lastName,
131 3
            'vorname' => $parameter->firstName,
132 3
            'mail' => $parameter->mail,
133 3
            'land' => $parameter->country,
134 3
            'ort' => $parameter->city,
135 3
            'plz' => $parameter->postalCode,
136 3
            'strasseHnr' => $parameter->street,
137 3
            'geburtsDatum' => $parameter->dateOfBirth ? $parameter->dateOfBirth->format('Y-m-d') : null,
138
        ]));
139
140 3
        $pagingElement = $dom->createElement('novagp:pagingParameter');
141 3
        $partnerSearchParameter->appendChild($pagingElement);
142
143 3
        return (string)$dom->saveXML();
144
    }
145
146
    /**
147
     * Create result object.
148
     *
149
     * @param XmlDocument $xml The xml document
150
     *
151
     * @return NovaSearchPartnerResult The mapped result
152
     */
153 3
    private function createResult(XmlDocument $xml): NovaSearchPartnerResult
154
    {
155 3
        $result = new NovaSearchPartnerResult();
156
157 3
        $xml = $xml->withoutNamespaces();
158
159
        // Find and append all messages
160 3
        foreach ($this->novaMessageParser->findNovaMessages($xml) as $message) {
161
            $result->addMessage($message);
162
        }
163
164
        // Root node
165 3
        $responseNode = $xml->queryFirstNode('/Envelope/Body/suchePartnerResponse');
166 3
        $partnerNodes = $xml->queryNodes('partner', $responseNode);
167
168
        /** @var DOMElement $partnerNode */
169 3
        foreach ($partnerNodes as $partnerNode) {
170 3
            $result->addPartner($this->createPartner($partnerNode, $xml));
171
        }
172
173 3
        return $result;
174
    }
175
176
    /**
177
     * Map partner node to NovaPartner object.
178
     *
179
     * @param DOMElement $partnerNode The partnerNode
180
     * @param XmlDocument $xml The xml document
181
     *
182
     * @return NovaPartner The new NovaPartner instance
183
     */
184 3
    private function createPartner(DOMElement $partnerNode, XmlDocument $xml): NovaPartner
185
    {
186 3
        $partner = new NovaPartner();
187
188 3
        $partner->tkId = $xml->getAttributeValue('@tkid', $partnerNode);
189 3
        $partner->ckm = $xml->findAttributeValue('@ckm', $partnerNode);
190 3
        $partner->cardNumber = $xml->findAttributeValue('@grundkartenNummer', $partnerNode);
191
192 3
        $changeDate = $xml->findAttributeValue('@mutDatum', $partnerNode);
193 3
        if ($changeDate !== null) {
194 3
            $partner->changedAt = $xml->createChronosFromXsDateTime($changeDate);
195
        }
196
197 3
        $partner->lastName = $xml->findAttributeValue('name/@name', $partnerNode);
198 3
        $partner->firstName = $xml->findAttributeValue('name/@vorname', $partnerNode);
199 3
        $partner->title = $xml->findAttributeValue('@titel', $partnerNode);
200
201 3
        $deceased = $xml->findAttributeValue('@verstorben', $partnerNode);
202 3
        if ($deceased !== null) {
203 3
            $partner->deceased = $deceased === 'false' ? 0 : 1;
204
        }
205
206
        // Date of birth can be empty sometimes
207 3
        $dateOfBirth = $xml->findAttributeValue('@geburtsDatum', $partnerNode);
208 3
        if ($dateOfBirth) {
209 3
            $dateOfBirth = Chronos::createFromFormat('Y-m-d', $dateOfBirth)->setTime(0, 0);
210 3
            $partner->dateOfBirth = $dateOfBirth;
0 ignored issues
show
Documentation Bug introduced by
It seems like $dateOfBirth can also be of type false. However, the property $dateOfBirth is declared as type Cake\Chronos\Chronos|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
211
        }
212
213 3
        $gender = $xml->findAttributeValue('@geschlecht', $partnerNode);
214 3
        $genderTypeId = $gender === 'MAENNLICH' ? GenderType::MEN : GenderType::WOMEN;
215 3
        $partner->genderTypeId = $genderTypeId;
216
217
        // Address
218 3
        $addressNodes = $xml->queryNodes('sitz/adresse', $partnerNode);
219
220
        // Could be empty, one, or more then one address: postal addresse, communication address etc.
221 3
        if ($addressNodes->length >= 1) {
222 3
            $addressNode = $xml->getFirstNode($addressNodes);
223
224 3
            $country = $xml->findAttributeValue('@land', $addressNode);
225 3
            $partner->country = $country;
226
227 3
            $city = $xml->findAttributeValue('@ort', $addressNode);
228 3
            $partner->city = $city;
229
230 3
            $postalCode = $xml->findAttributeValue('@plz', $addressNode);
231 3
            $partner->postalCode = $postalCode;
232
233 3
            $additional = $xml->findAttributeValue('@adressZusatz', $addressNode);
234 3
            if ($additional !== null) {
235
                $partner->additional = $additional;
236
            }
237
238 3
            $street = $xml->findAttributeValue('@strasseHnr', $addressNode);
239 3
            $partner->street = $street;
240
241 3
            $poBox = $xml->findAttributeValue('@postfach', $addressNode);
242 3
            if ($poBox !== null) {
243 3
                $partner->poBox = $poBox;
244
            }
245
        }
246
247
        // MOBIL, FESTNETZ or MAIL
248 3
        $phoneNumber = $xml->findAttributeValue('festnetz/@formatiertE123', $partnerNode);
249 3
        if ($phoneNumber !== null) {
250 3
            $partner->phoneNumber = str_replace(' ', '', $phoneNumber);
251
        }
252
253 3
        $mobileNumber = $xml->findAttributeValue('mobil/@formatiertE123', $partnerNode);
254 3
        if ($mobileNumber !== null) {
255 3
            $partner->mobileNumber = str_replace(' ', '', $mobileNumber);
256
        }
257
258 3
        $email = $xml->findAttributeValue('@email', $partnerNode);
259 3
        if ($email && filter_var($email, FILTER_VALIDATE_EMAIL) !== false) {
260 3
            $partner->email = $email;
261
        }
262
263 3
        return $partner;
264
    }
265
}
266