Passed
Pull Request — master (#7)
by
unknown
14:53
created

DynadotApi::setRenewOption()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 45
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 45
ccs 25
cts 25
cp 1
rs 9.2408
cc 5
nc 7
nop 2
crap 5
1
<?php
2
3
namespace Level23\Dynadot;
4
5
use Psr\Log\LogLevel;
6
use Sabre\Xml\Reader;
7
use GuzzleHttp\Client;
8
use Sabre\Xml\Service;
9
use Psr\Log\LoggerInterface;
10
use Psr\Http\Message\StreamInterface;
11
use Level23\Dynadot\ResultObjects\SetNsResponse;
12
use Level23\Dynadot\ResultObjects\DomainResponse;
13
use Level23\Dynadot\Exception\DynadotApiException;
14
use Level23\Dynadot\ResultObjects\GeneralResponse;
15
use Level23\Dynadot\ResultObjects\DomainInfoResponse;
16
use Level23\Dynadot\ResultObjects\GetContactResponse;
17
use Level23\Dynadot\Exception\ApiHttpCallFailedException;
18
use Level23\Dynadot\ResultObjects\ListDomainInfoResponse;
19
use Level23\Dynadot\Exception\ApiLimitationExceededException;
20
use Level23\Dynadot\ResultObjects\RenewOptionResponse\SetRenewOptionHeader;
21
use Level23\Dynadot\ResultObjects\RenewOptionResponse\SetRenewOptionResponse;
22
23
/**
24
 * Class DynadotApi
25
 *
26
 * @package Level23\Dynadot
27
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
28
 */
29
class DynadotApi
30
{
31
    const DYNADOT_API_URL = 'https://api.dynadot.com/api3.xml';
32
33
    /**
34
     * This options array is used by Guzzle.
35
     *
36
     * We currently use it to set the Mock Handler in unit testing.
37
     *
38
     * @var array
39
     */
40
    protected $guzzleOptions = [];
41
42
    /**
43
     * Dynadot's API key we should use for HTTP calls.
44
     *
45
     * @var string
46
     */
47
    protected $apiKey;
48
49
    /**
50
     * Logger for writing debug info
51
     *
52
     * @var LoggerInterface|null
53
     */
54
    protected $logger;
55
56
    /**
57
     * Changes boolean values like "no" and "yes" into false and true.
58
     *
59
     * @return bool
60
     * @throws DynadotApiException
61
     * @var \Closure
62
     */
63
    protected $booleanDeserializer;
64
65
    /**
66
     * Return the contact id
67
     *
68
     * @param Reader $reader
69
     *
70
     * @return int
71
     * @var \Closure
72
     */
73
    protected $contactIdDeserializer;
74
75
    /**
76
     * DynadotApi constructor.
77
     *
78
     * @param string                        $apiKey The API key we should use while communicating with the Dynadot API.
79
     * @param \Psr\Log\LoggerInterface|null $logger
80
     *
81
     * @internal param $Logger
82
     */
83 28
    public function __construct(string $apiKey, LoggerInterface $logger = null)
84
    {
85 28
        $this->setApiKey($apiKey);
86 28
        $this->logger = $logger;
87
88
        /**
89
         * Set the default guzzle options
90
         */
91 28
        $this->setGuzzleOptions([
92 28
            'max'             => 5,
93 28
            'referer'         => false,
94 28
            'protocols'       => ['https'],
95 28
            'connect_timeout' => 30,
96 28
        ]);
97
98
        /**
99
         * Changes boolean values like "no" and "yes" into false and true.
100
         *
101
         * @param \Sabre\Xml\Reader $reader
102
         *
103
         * @return bool
104
         * @throws \Level23\Dynadot\Exception\DynadotApiException
105
         * @throws \Sabre\Xml\LibXMLException
106
         * @throws \Sabre\Xml\ParseException
107
         */
108 28
        $this->booleanDeserializer = function (Reader $reader) {
109 3
            $value = $reader->parseInnerTree();
110 3
            if (is_string($value)) {
111 3
                $value = strtolower($value);
112
            }
113
114 3
            if ($value != 'yes' && $value != 'no') {
115
                throw new DynadotApiException('Error, received incorrect boolean value ' . var_export($value, true));
116
            }
117
118 3
            return ($value !== 'no');
119 28
        };
120
121
        /**
122
         * Return the contact id
123
         *
124
         * @param Reader $reader
125
         *
126
         * @return int
127
         * @throws \Sabre\Xml\LibXMLException
128
         * @throws \Sabre\Xml\ParseException
129
         */
130 28
        $this->contactIdDeserializer = function (Reader $reader) {
131 3
            $children = (array)$reader->parseInnerTree();
132
133 3
            return $children[0]['value'];
134 28
        };
135
    }
136
137
    /**
138
     * @param array $optionsArray
139
     */
140 28
    public function setGuzzleOptions(array $optionsArray): void
141
    {
142 28
        $this->guzzleOptions = $optionsArray;
143
    }
144
145
    /**
146
     * Get info about a domain
147
     *
148
     * @param string $domain
149
     *
150
     * @return DomainResponse\Domain
151
     * @throws \Level23\Dynadot\Exception\ApiHttpCallFailedException
152
     * @throws \Level23\Dynadot\Exception\DynadotApiException
153
     * @throws \Sabre\Xml\ParseException
154
     * @throws \GuzzleHttp\Exception\GuzzleException
155
     */
156 7
    public function getDomainInfo(string $domain): DomainResponse\Domain
157
    {
158 7
        $this->log(LogLevel::INFO, 'Retrieve info for domain: ' . $domain);
159
160 7
        $requestData = [
161 7
            'domain'  => $domain,
162 7
            'command' => 'domain_info',
163 7
        ];
164
165
        // perform the API call
166 7
        $response = $this->performRawApiCall($requestData);
167
168
        // start parsing XML data using Sabre
169 6
        $sabreService = new Service();
170
171
        // set mapping
172 6
        $sabreService->elementMap = [
173 6
            '{}NameServers'          => function (Reader $reader) {
174
175 2
                $nameservers = [];
176 2
                $id          = '';
177
178 2
                $children = (array)$reader->parseInnerTree();
179
180 2
                foreach ($children as $child) {
181 2
                    if ($child['name'] == '{}ServerId') {
182 2
                        $id = $child['value'];
183 2
                    } elseif ($child['name'] == '{}ServerName') {
184 2
                        if (!empty($id) && !empty($child['value'])) {
185 2
                            $nameserver = new DomainResponse\NameServer();
186
187 2
                            $nameserver->ServerId   = $id;
0 ignored issues
show
Documentation Bug introduced by
The property $ServerId was declared of type integer, but $id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
188 2
                            $nameserver->ServerName = $child['value'];
189
190 2
                            $nameservers[] = $nameserver;
191
                        }
192 2
                        $id = null;
193
                    }
194
                }
195
196 2
                return $nameservers;
197 6
            },
198 6
            '{}Registrant'           => $this->contactIdDeserializer,
199 6
            '{}Admin'                => $this->contactIdDeserializer,
200 6
            '{}Technical'            => $this->contactIdDeserializer,
201 6
            '{}Billing'              => $this->contactIdDeserializer,
202 6
            '{}isForSale'            => $this->booleanDeserializer,
203 6
            '{}Hold'                 => $this->booleanDeserializer,
204 6
            '{}RegistrantUnverified' => $this->booleanDeserializer,
205 6
            '{}UdrpLocked'           => $this->booleanDeserializer,
206 6
            '{}Disabled'             => $this->booleanDeserializer,
207 6
            '{}Locked'               => $this->booleanDeserializer,
208 6
            '{}WithAds'              => $this->booleanDeserializer,
209 6
        ];
210
211
        // map certain values to objects
212 6
        $sabreService->mapValueObject('{}DomainInfoResponse', DomainInfoResponse\DomainInfoResponse::class);
213 6
        $sabreService->mapValueObject('{}DomainInfoHeader', DomainInfoResponse\DomainInfoHeader::class);
214 6
        $sabreService->mapValueObject('{}DomainInfoContent', DomainInfoResponse\DomainInfoContent::class);
215 6
        $sabreService->mapValueObject('{}Domain', DomainResponse\Domain::class);
216 6
        $sabreService->mapValueObject('{}NameServerSettings', DomainResponse\NameServerSettings::class);
217 6
        $sabreService->mapValueObject('{}Whois', DomainResponse\Whois::class);
218 6
        $sabreService->mapValueObject('{}Folder', DomainResponse\Folder::class);
219 6
        $sabreService->mapValueObject('{}Response', GeneralResponse\Response::class);
220 6
        $sabreService->mapValueObject('{}ResponseHeader', GeneralResponse\ResponseHeader::class);
221
222 6
        $this->log(LogLevel::DEBUG, 'Start parsing response XML');
223
224 6
        $contents = $response->getContents();
225
226
        // parse the data
227 6
        $resultData = $sabreService->parse($contents);
228
229 5
        if (!$resultData instanceof DomainInfoResponse\DomainInfoResponse) {
230 2
            throw new DynadotApiException('We failed to parse the response');
231
        }
232
233 3
        $code = $resultData->DomainInfoHeader->ResponseCode ?? $resultData->DomainInfoHeader->SuccessCode;
0 ignored issues
show
Bug introduced by
The property ResponseCode does not seem to exist on Level23\Dynadot\ResultOb...sponse\DomainInfoHeader.
Loading history...
234 3
        if ($code != GeneralResponse\ResponseHeader::RESPONSECODE_OK) {
235 1
            throw new DynadotApiException($resultData->DomainInfoHeader->Error);
236
        }
237
238 2
        if ($resultData->DomainInfoHeader !== null) {
239
            /**
240
             * Check if the API call was successful. If not, return the error
241
             */
242 2
            $code = $resultData->DomainInfoHeader->SuccessCode;
243 2
            if ($code != DomainInfoResponse\DomainInfoHeader::SUCCESSCODE_OK) {
244
                throw new DynadotApiException($resultData->DomainInfoHeader->Error);
245
            }
246
        }
247
248 2
        $this->log(LogLevel::DEBUG, 'Returning domain info');
249
250
        // Here we know our API call was succesful, return the domain info.
251 2
        return $resultData->DomainInfoContent->Domain;
252
    }
253
254
    /**
255
     * Log a message to our logger, if we have any.
256
     *
257
     * @param string $level
258
     * @param string $message
259
     */
260 27
    protected function log(string $level, string $message): void
261
    {
262 27
        if ($this->logger instanceof LoggerInterface) {
263 1
            $this->logger->log($level, $message);
264
        }
265
    }
266
267
    /**
268
     * Performs the actual API call (internal method)
269
     *
270
     * @param array $requestData
271
     *
272
     * @return \Psr\Http\Message\StreamInterface
273
     * @throws \GuzzleHttp\Exception\GuzzleException
274
     * @throws \Level23\Dynadot\Exception\ApiHttpCallFailedException
275
     */
276 26
    protected function performRawApiCall(array $requestData): StreamInterface
277
    {
278 26
        $this->log(LogLevel::DEBUG, 'Perform raw call: ' . var_export($requestData, true));
279
280
        // transform the request data into a valid query string
281 26
        $requestDataHttp = http_build_query($requestData);
282
283
        // spawn Guzzle
284 26
        $client = new Client($this->guzzleOptions);
285
286 26
        $url = self::DYNADOT_API_URL .
287 26
            '?key=' . urlencode($this->getApiKey()) .
288 26
            ($requestDataHttp ? '&' . $requestDataHttp : '');
289
290 26
        $this->log(LogLevel::DEBUG, 'Start new guzzle request with URL: ' . $url);
291
292
        // start a request with out API key and optionally our request data
293 26
        $response = $client->request('GET', $url);
294
295 26
        $this->log(LogLevel::DEBUG, 'Received response with status code ' . $response->getStatusCode());
296
297
        // if we did not get a HTTP 200 response, our HTTP call failed (which is different from a failed API call)
298 26
        if ($response->getStatusCode() != 200) {
299 1
            $this->log(LogLevel::ALERT, 'Received wrong HTTP status code: ' . $response->getStatusCode());
300
            // not ok
301 1
            throw new ApiHttpCallFailedException(
302 1
                'HTTP API call failed, expected 200 status, got ' . $response->getStatusCode()
303 1
            );
304
        }
305
306
        // Return the response body (which is a stream coming from Guzzle).
307
        // Sabre XML semi-handles streams (it will just get the contents of the stream using stream_get_contents) so
308
        // this should work! ;)
309 25
        return $response->getBody();
310
    }
311
312
    /**
313
     * @return string
314
     */
315 27
    public function getApiKey(): string
316
    {
317 27
        return $this->apiKey;
318
    }
319
320
    /**
321
     * @param string $apiKey
322
     */
323 28
    public function setApiKey(string $apiKey): void
324
    {
325 28
        $this->apiKey = $apiKey;
326
    }
327
328
    /**
329
     * Set nameservers for a domain (max 13). An exception will be thrown in case of an error.
330
     *
331
     * @param string $domain The domain where to set the nameservers for.
332
     * @param array  $nameservers
333
     *
334
     * @throws \GuzzleHttp\Exception\GuzzleException
335
     * @throws \Level23\Dynadot\Exception\ApiHttpCallFailedException
336
     * @throws \Level23\Dynadot\Exception\ApiLimitationExceededException
337
     * @throws \Level23\Dynadot\Exception\DynadotApiException
338
     * @throws \Sabre\Xml\ParseException
339
     */
340 6
    public function setNameserversForDomain(string $domain, array $nameservers): void
341
    {
342 6
        $this->log(LogLevel::DEBUG, 'Set ' . sizeof($nameservers) . ' nameservers for domain ' . $domain);
343 6
        $requestData = [
344 6
            'command' => 'set_ns',
345 6
            'domain'  => $domain,
346 6
        ];
347
348 6
        if (sizeof($nameservers) > 13) {
349
            // index starts at 0, so we should check if the index is greater than 12 (which is 13 nameservers)
350 1
            throw new ApiLimitationExceededException(
351 1
                'Can not define more than 13 nameservers through the API'
352 1
            );
353
        }
354
355 5
        $idx = 0;
356
        // check if there are more than 13 nameservers defined
357 5
        foreach ($nameservers as $nameserver) {
358 5
            $requestData['ns' . $idx++] = $nameserver;
359
        }
360
361
        // perform the API call
362 5
        $response = $this->performRawApiCall($requestData);
363
364 5
        $this->log(LogLevel::DEBUG, 'API call executed, parsing response...');
365
366
        // start parsing XML data using Sabre
367 5
        $sabreService = new Service();
368
369
        // map certain values to objects
370 5
        $sabreService->mapValueObject('{}SetNsResponse', SetNsResponse\SetNsResponse::class);
371 5
        $sabreService->mapValueObject('{}SetNsHeader', SetNsResponse\SetNsHeader::class);
372 5
        $sabreService->mapValueObject('{}Response', GeneralResponse\Response::class);
373 5
        $sabreService->mapValueObject('{}ResponseHeader', GeneralResponse\ResponseHeader::class);
374
375
        // parse the data
376 5
        $resultData = $sabreService->parse($response->getContents());
377
378
        // General error, like incorrect api key
379 4
        if ($resultData instanceof GeneralResponse\Response) {
380 1
            $code = $resultData->ResponseHeader->ResponseCode;
381 1
            if ($code != GeneralResponse\ResponseHeader::RESPONSECODE_OK) {
382 1
                throw new DynadotApiException($resultData->ResponseHeader->Error);
383
            }
384
        }
385
386 3
        if (!$resultData instanceof SetNsResponse\SetNsResponse) {
387 1
            throw new DynadotApiException('We failed to parse the response');
388
        }
389
390
        /**
391
         * Check if the API call was successful. If not, return the error
392
         */
393 2
        $code = $resultData->SetNsHeader->SuccessCode;
394 2
        if ($code != SetNsResponse\SetNsHeader::SUCCESSCODE_OK) {
395 1
            throw new DynadotApiException($resultData->SetNsHeader->Error);
396
        }
397
398 1
        $this->log(LogLevel::DEBUG, 'Received correct response. Everything is ok!');
399
    }
400
401
    /**
402
     * List all domains in the account. We will return an array with Domain objects
403
     *
404
     * @return DomainResponse\Domain[]
405
     * @throws \GuzzleHttp\Exception\GuzzleException
406
     * @throws \Level23\Dynadot\Exception\ApiHttpCallFailedException
407
     * @throws \Level23\Dynadot\Exception\DynadotApiException
408
     * @throws \Sabre\Xml\ParseException
409
     */
410 5
    public function getDomainList(): array
411
    {
412 5
        $this->log(LogLevel::DEBUG, 'Start retrieving all domains');
413 5
        $requestData = [
414 5
            'command' => 'list_domain',
415 5
        ];
416
417
        // perform the API call
418 5
        $response = $this->performRawApiCall($requestData);
419
420 5
        $this->log(LogLevel::DEBUG, 'Start parsing response XML');
421
422
        // start parsing XML data using Sabre
423 5
        $sabreService = new Service();
424
425
        // set mapping
426 5
        $sabreService->elementMap = [
427 5
            '{}NameServers'          => function (Reader $reader) {
428
429
                $nameservers = [];
430
                $id          = '';
431
432
                $children = (array)$reader->parseInnerTree();
433
434
                foreach ($children as $child) {
435
                    if ($child['name'] == '{}ServerId') {
436
                        $id = $child['value'];
437
                    } elseif ($child['name'] == '{}ServerName') {
438
                        if (!empty($id) && !empty($child['value'])) {
439
                            $nameserver             = new DomainResponse\NameServer();
440
                            $nameserver->ServerId   = $id;
0 ignored issues
show
Documentation Bug introduced by
The property $ServerId was declared of type integer, but $id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
441
                            $nameserver->ServerName = $child['value'];
442
443
                            $nameservers[] = $nameserver;
444
                        }
445
                        $id = null;
446
                    }
447
                }
448
449
                return $nameservers;
450 5
            },
451 5
            '{}DomainInfoList'       => function (Reader $reader) {
452 1
                $domains = [];
453
454 1
                $tree = (array)$reader->parseInnerTree();
455
456 1
                foreach ($tree as $item) {
457 1
                    foreach ($item['value'] as $domain) {
458 1
                        $domains[] = $domain['value'];
459
                    }
460
                }
461
462 1
                return $domains;
463 5
            },
464 5
            '{}Registrant'           => $this->contactIdDeserializer,
465 5
            '{}Admin'                => $this->contactIdDeserializer,
466 5
            '{}Technical'            => $this->contactIdDeserializer,
467 5
            '{}Billing'              => $this->contactIdDeserializer,
468 5
            '{}isForSale'            => $this->booleanDeserializer,
469 5
            '{}Hold'                 => $this->booleanDeserializer,
470 5
            '{}RegistrantUnverified' => $this->booleanDeserializer,
471 5
            '{}UdrpLocked'           => $this->booleanDeserializer,
472 5
            '{}Disabled'             => $this->booleanDeserializer,
473 5
            '{}Locked'               => $this->booleanDeserializer,
474 5
            '{}WithAds'              => $this->booleanDeserializer,
475 5
        ];
476
477
        // map certain values to objects
478 5
        $sabreService->mapValueObject('{}ListDomainInfoResponse', ListDomainInfoResponse\ListDomainInfoResponse::class);
479 5
        $sabreService->mapValueObject('{}ListDomainInfoHeader', ListDomainInfoResponse\ListDomainInfoHeader::class);
480 5
        $sabreService->mapValueObject('{}ListDomainInfoContent', ListDomainInfoResponse\ListDomainInfoContent::class);
481 5
        $sabreService->mapValueObject('{}Domain', DomainResponse\Domain::class);
482 5
        $sabreService->mapValueObject('{}NameServerSettings', DomainResponse\NameServerSettings::class);
483 5
        $sabreService->mapValueObject('{}Whois', DomainResponse\Whois::class);
484 5
        $sabreService->mapValueObject('{}Folder', DomainResponse\Folder::class);
485 5
        $sabreService->mapValueObject('{}Response', GeneralResponse\Response::class);
486 5
        $sabreService->mapValueObject('{}ResponseHeader', GeneralResponse\ResponseHeader::class);
487
488
        // parse the data
489 5
        $resultData = $sabreService->parse($response->getContents());
490
491
        // General error, like incorrect api key
492 4
        if ($resultData instanceof GeneralResponse\Response) {
493 1
            $code = $resultData->ResponseHeader->ResponseCode;
494 1
            if ($code != GeneralResponse\ResponseHeader::RESPONSECODE_OK) {
495 1
                throw new DynadotApiException($resultData->ResponseHeader->Error);
496
            }
497
        }
498
499 3
        if (!$resultData instanceof ListDomainInfoResponse\ListDomainInfoResponse) {
500 1
            throw new DynadotApiException('We failed to parse the response');
501
        }
502
503
        /**
504
         * Check if the API call was successful. If not, return the error
505
         */
506 2
        $code = $resultData->ListDomainInfoHeader->ResponseCode;
507 2
        if ($code != ListDomainInfoResponse\ListDomainInfoHeader::RESPONSECODE_OK) {
508 1
            throw new DynadotApiException($resultData->ListDomainInfoHeader->Error);
509
        }
510
511 1
        return $resultData->ListDomainInfoContent->DomainInfoList;
512
    }
513
514
    /**
515
     * Get contact information for a specific contact ID
516
     *
517
     * @param int $contactId The contact ID we should request
518
     *
519
     * @return GetContactResponse\Contact
520
     * @throws \GuzzleHttp\Exception\GuzzleException
521
     * @throws \Level23\Dynadot\Exception\ApiHttpCallFailedException
522
     * @throws \Level23\Dynadot\Exception\DynadotApiException
523
     * @throws \Sabre\Xml\ParseException
524
     */
525 5
    public function getContactInfo(int $contactId): GetContactResponse\Contact
526
    {
527 5
        $this->log(LogLevel::DEBUG, 'Fetch contact details for id ' . $contactId);
528
529 5
        $requestData = [
530 5
            'command'    => 'get_contact',
531 5
            'contact_id' => $contactId,
532 5
        ];
533
534
        // perform the API call
535 5
        $response = $this->performRawApiCall($requestData);
536
537 5
        $this->log(LogLevel::DEBUG, 'Start parsing result');
538
539
        // start parsing XML data using Sabre
540 5
        $sabreService = new Service();
541
542
        // map certain values to objects
543 5
        $sabreService->mapValueObject('{}GetContactResponse', GetContactResponse\GetContactResponse::class);
544 5
        $sabreService->mapValueObject('{}GetContactHeader', GetContactResponse\GetContactHeader::class);
545 5
        $sabreService->mapValueObject('{}GetContactContent', GetContactResponse\GetContactContent::class);
546 5
        $sabreService->mapValueObject('{}Contact', GetContactResponse\Contact::class);
547 5
        $sabreService->mapValueObject('{}Response', GeneralResponse\Response::class);
548 5
        $sabreService->mapValueObject('{}ResponseHeader', GeneralResponse\ResponseHeader::class);
549
550
        // parse the data
551 5
        $resultData = $sabreService->parse($response->getContents());
552
553
        // General error, like incorrect api key
554 4
        if ($resultData instanceof GeneralResponse\Response) {
555 1
            $code = $resultData->ResponseHeader->ResponseCode;
556 1
            if ($code != GeneralResponse\ResponseHeader::RESPONSECODE_OK) {
557 1
                throw new DynadotApiException($resultData->ResponseHeader->Error);
558
            }
559
        }
560
561 3
        if (!$resultData instanceof GetContactResponse\GetContactResponse) {
562 1
            throw new DynadotApiException('We failed to parse the response');
563
        }
564
565
        /**
566
         * Check if the API call was successful. If not, return the error
567
         */
568 2
        $code = $resultData->GetContactHeader->ResponseCode;
569 2
        if ($code != GetContactResponse\GetContactHeader::RESPONSECODE_OK) {
570 1
            throw new DynadotApiException($resultData->GetContactHeader->Error);
571
        }
572
573 1
        return $resultData->GetContactContent->Contact;
574
    }
575
576
    /**
577
     * @throws \Level23\Dynadot\Exception\DynadotApiException
578
     * @throws \Sabre\Xml\ParseException
579
     * @throws \GuzzleHttp\Exception\GuzzleException
580
     * @throws \Level23\Dynadot\Exception\ApiHttpCallFailedException
581
     */
582 4
    public function setRenewOption(string $domain, string $renewOption): bool
583
    {
584 4
        $this->log(LogLevel::INFO, 'Set auto renew for: ' . $domain . ' to: ' . $renewOption);
585
586 4
        $requestData = [
587 4
            'command'      => 'set_renew_option',
588 4
            'domain'       => $domain,
589 4
            'renew_option' => $renewOption,
590 4
        ];
591
592
        // perform the API call
593 4
        $response = $this->performRawApiCall($requestData);
594
595 4
        $this->log(LogLevel::DEBUG, 'Start parsing result');
596
597
        // start parsing XML data using Sabre
598 4
        $sabreService = new Service();
599
600
        // map certain values to objects
601 4
        $sabreService->mapValueObject('{}SetRenewOptionResponse', SetRenewOptionResponse::class);
602 4
        $sabreService->mapValueObject('{}SetRenewOptionHeader', SetRenewOptionHeader::class);
603 4
        $sabreService->mapValueObject('{}Response', GeneralResponse\Response::class);
604 4
        $sabreService->mapValueObject('{}ResponseHeader', GeneralResponse\ResponseHeader::class);
605
606
        // parse the data
607 4
        $resultData = $sabreService->parse($response->getContents());
608
609
        // General error, like incorrect api key
610 4
        if ($resultData instanceof GeneralResponse\Response) {
611 1
            $code = $resultData->ResponseHeader->ResponseCode;
612 1
            if ($code != GeneralResponse\ResponseHeader::RESPONSECODE_OK) {
613 1
                throw new DynadotApiException($resultData->ResponseHeader->Error);
614
            }
615
        }
616
617 3
        if (!$resultData instanceof SetRenewOptionResponse) {
618 1
            throw new DynadotApiException('We failed to parse the response');
619
        }
620
621 2
        $code = $resultData->SetRenewOptionHeader->SuccessCode;
622 2
        if ($code != SetRenewOptionHeader::SUCCESSCODE_OK) {
623 1
            throw new DynadotApiException((string)$resultData->SetRenewOptionHeader->Error);
624
        }
625
626 1
        return true;
627
    }
628
}
629